| @@ -1,1560 +1,1560 @@ | | | @@ -1,1560 +1,1560 @@ |
1 | /* $NetBSD: tape.c,v 1.69 2020/09/03 19:31:34 bouyer Exp $ */ | | 1 | /* $NetBSD: tape.c,v 1.70 2021/03/11 01:13:11 msaitoh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1983, 1993 | | 4 | * Copyright (c) 1983, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * (c) UNIX System Laboratories, Inc. | | 6 | * (c) UNIX System Laboratories, Inc. |
7 | * All or some portions of this file are derived from material licensed | | 7 | * All or some portions of this file are derived from material licensed |
8 | * to the University of California by American Telephone and Telegraph | | 8 | * to the University of California by American Telephone and Telegraph |
9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | | 9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with |
10 | * the permission of UNIX System Laboratories, Inc. | | 10 | * the permission of UNIX System Laboratories, Inc. |
11 | * | | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | | 12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | | 13 | * modification, are permitted provided that the following conditions |
14 | * are met: | | 14 | * are met: |
15 | * 1. Redistributions of source code must retain the above copyright | | 15 | * 1. Redistributions of source code must retain the above copyright |
16 | * notice, this list of conditions and the following disclaimer. | | 16 | * notice, this list of conditions and the following disclaimer. |
17 | * 2. Redistributions in binary form must reproduce the above copyright | | 17 | * 2. Redistributions in binary form must reproduce the above copyright |
18 | * notice, this list of conditions and the following disclaimer in the | | 18 | * notice, this list of conditions and the following disclaimer in the |
19 | * documentation and/or other materials provided with the distribution. | | 19 | * documentation and/or other materials provided with the distribution. |
20 | * 3. Neither the name of the University nor the names of its contributors | | 20 | * 3. Neither the name of the University nor the names of its contributors |
21 | * may be used to endorse or promote products derived from this software | | 21 | * may be used to endorse or promote products derived from this software |
22 | * without specific prior written permission. | | 22 | * without specific prior written permission. |
23 | * | | 23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
34 | * SUCH DAMAGE. | | 34 | * SUCH DAMAGE. |
35 | */ | | 35 | */ |
36 | | | 36 | |
37 | #include <sys/cdefs.h> | | 37 | #include <sys/cdefs.h> |
38 | #ifndef lint | | 38 | #ifndef lint |
39 | #if 0 | | 39 | #if 0 |
40 | static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95"; | | 40 | static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95"; |
41 | #else | | 41 | #else |
42 | __RCSID("$NetBSD: tape.c,v 1.69 2020/09/03 19:31:34 bouyer Exp $"); | | 42 | __RCSID("$NetBSD: tape.c,v 1.70 2021/03/11 01:13:11 msaitoh Exp $"); |
43 | #endif | | 43 | #endif |
44 | #endif /* not lint */ | | 44 | #endif /* not lint */ |
45 | | | 45 | |
46 | #include <sys/param.h> | | 46 | #include <sys/param.h> |
47 | #include <sys/file.h> | | 47 | #include <sys/file.h> |
48 | #include <sys/ioctl.h> | | 48 | #include <sys/ioctl.h> |
49 | #include <sys/mtio.h> | | 49 | #include <sys/mtio.h> |
50 | #include <sys/stat.h> | | 50 | #include <sys/stat.h> |
51 | | | 51 | |
52 | #include <ufs/ufs/dinode.h> | | 52 | #include <ufs/ufs/dinode.h> |
53 | #include <protocols/dumprestore.h> | | 53 | #include <protocols/dumprestore.h> |
54 | | | 54 | |
55 | #include <err.h> | | 55 | #include <err.h> |
56 | #include <errno.h> | | 56 | #include <errno.h> |
57 | #include <paths.h> | | 57 | #include <paths.h> |
58 | #include <setjmp.h> | | 58 | #include <setjmp.h> |
59 | #include <stdio.h> | | 59 | #include <stdio.h> |
60 | #include <stdlib.h> | | 60 | #include <stdlib.h> |
61 | #include <string.h> | | 61 | #include <string.h> |
62 | #include <time.h> | | 62 | #include <time.h> |
63 | #include <unistd.h> | | 63 | #include <unistd.h> |
64 | | | 64 | |
65 | #include <md5.h> | | 65 | #include <md5.h> |
66 | #include <rmd160.h> | | 66 | #include <rmd160.h> |
67 | #include <sha1.h> | | 67 | #include <sha1.h> |
68 | | | 68 | |
69 | #include "restore.h" | | 69 | #include "restore.h" |
70 | #include "extern.h" | | 70 | #include "extern.h" |
71 | | | 71 | |
72 | static u_int32_t fssize = MAXBSIZE; | | 72 | static u_int32_t fssize = MAXBSIZE; |
73 | static int mt = -1; | | 73 | static int mt = -1; |
74 | static int pipein = 0; | | 74 | static int pipein = 0; |
75 | static char magtape[BUFSIZ]; | | 75 | static char magtape[BUFSIZ]; |
76 | static int blkcnt; | | 76 | static int blkcnt; |
77 | static int numtrec; | | 77 | static int numtrec; |
78 | static char *tapebuf; | | 78 | static char *tapebuf; |
79 | static union u_spcl endoftapemark; | | 79 | static union u_spcl endoftapemark; |
80 | static int blksread; /* blocks read since last header */ | | 80 | static int blksread; /* blocks read since last header */ |
81 | static int tpblksread = 0; /* TP_BSIZE blocks read */ | | 81 | static int tpblksread = 0; /* TP_BSIZE blocks read */ |
82 | static int tapesread; | | 82 | static int tapesread; |
83 | static jmp_buf restart; | | 83 | static jmp_buf restart; |
84 | static int gettingfile = 0; /* restart has a valid frame */ | | 84 | static int gettingfile = 0; /* restart has a valid frame */ |
85 | #ifdef RRESTORE | | 85 | #ifdef RRESTORE |
86 | static const char *host = NULL; | | 86 | static const char *host = NULL; |
87 | #endif | | 87 | #endif |
88 | | | 88 | |
89 | static int ofile; | | 89 | static int ofile; |
90 | static char lnkbuf[MAXPATHLEN + 1]; | | 90 | static char lnkbuf[MAXPATHLEN + 1]; |
91 | static int pathlen; | | 91 | static int pathlen; |
92 | | | 92 | |
93 | int oldinofmt; /* old inode format conversion required */ | | 93 | int oldinofmt; /* old inode format conversion required */ |
94 | int Bcvt; /* Swap Bytes (for CCI or sun) */ | | 94 | int Bcvt; /* Swap Bytes (for CCI or sun) */ |
95 | | | 95 | |
96 | const struct digest_desc *ddesc; | | 96 | const struct digest_desc *ddesc; |
97 | | | 97 | |
98 | static union digest_context { | | 98 | static union digest_context { |
99 | MD5_CTX dc_MD5; | | 99 | MD5_CTX dc_MD5; |
100 | SHA1_CTX dc_SHA1; | | 100 | SHA1_CTX dc_SHA1; |
101 | RMD160_CTX dc_RMD160; | | 101 | RMD160_CTX dc_RMD160; |
102 | } dcontext; | | 102 | } dcontext; |
103 | | | 103 | |
104 | /* | | 104 | /* |
105 | * 32 for md5; 40 for sha1 and rmd160 | | 105 | * 32 for md5; 40 for sha1 and rmd160 |
106 | * plus a null terminator. | | 106 | * plus a null terminator. |
107 | */ | | 107 | */ |
108 | #define DIGEST_BUFFER_SIZE (40 + 1) | | 108 | #define DIGEST_BUFFER_SIZE (40 + 1) |
109 | | | 109 | |
110 | #define FLUSHTAPEBUF() blkcnt = ntrec + 1 | | 110 | #define FLUSHTAPEBUF() blkcnt = ntrec + 1 |
111 | | | 111 | |
112 | union u_ospcl { | | 112 | union u_ospcl { |
113 | char dummy[TP_BSIZE]; | | 113 | char dummy[TP_BSIZE]; |
114 | struct s_ospcl { | | 114 | struct s_ospcl { |
115 | int32_t c_type; | | 115 | int32_t c_type; |
116 | int32_t c_date; | | 116 | int32_t c_date; |
117 | int32_t c_ddate; | | 117 | int32_t c_ddate; |
118 | int32_t c_volume; | | 118 | int32_t c_volume; |
119 | int32_t c_tapea; | | 119 | int32_t c_tapea; |
120 | u_int16_t c_inumber; | | 120 | u_int16_t c_inumber; |
121 | int32_t c_magic; | | 121 | int32_t c_magic; |
122 | int32_t c_checksum; | | 122 | int32_t c_checksum; |
123 | struct odinode { | | 123 | struct odinode { |
124 | unsigned short odi_mode; | | 124 | unsigned short odi_mode; |
125 | u_int16_t odi_nlink; | | 125 | u_int16_t odi_nlink; |
126 | u_int16_t odi_uid; | | 126 | u_int16_t odi_uid; |
127 | u_int16_t odi_gid; | | 127 | u_int16_t odi_gid; |
128 | int32_t odi_size; | | 128 | int32_t odi_size; |
129 | int32_t odi_rdev; | | 129 | int32_t odi_rdev; |
130 | char odi_addr[36]; | | 130 | char odi_addr[36]; |
131 | int32_t odi_atime; | | 131 | int32_t odi_atime; |
132 | int32_t odi_mtime; | | 132 | int32_t odi_mtime; |
133 | int32_t odi_ctime; | | 133 | int32_t odi_ctime; |
134 | } c_odinode; | | 134 | } c_odinode; |
135 | int32_t c_count; | | 135 | int32_t c_count; |
136 | char c_addr[256]; | | 136 | char c_addr[256]; |
137 | } s_ospcl; | | 137 | } s_ospcl; |
138 | }; | | 138 | }; |
139 | | | 139 | |
140 | static void accthdr(struct s_spcl *); | | 140 | static void accthdr(struct s_spcl *); |
141 | static int checksum(int *); | | 141 | static int checksum(int *); |
142 | static void findinode(struct s_spcl *); | | 142 | static void findinode(struct s_spcl *); |
143 | static void findtapeblksize(void); | | 143 | static void findtapeblksize(void); |
144 | static void getbitmap(char **); | | 144 | static void getbitmap(char **); |
145 | static int gethead(struct s_spcl *); | | 145 | static int gethead(struct s_spcl *); |
146 | static void readtape(char *); | | 146 | static void readtape(char *); |
147 | static void setdumpnum(void); | | 147 | static void setdumpnum(void); |
148 | static void terminateinput(void); | | 148 | static void terminateinput(void); |
149 | static void xtrfile(char *, long); | | 149 | static void xtrfile(char *, long); |
150 | static void xtrlnkfile(char *, long); | | 150 | static void xtrlnkfile(char *, long); |
151 | __dead static void xtrlnkskip(char *, long); | | 151 | __dead static void xtrlnkskip(char *, long); |
152 | static void xtrskip(char *, long); | | 152 | static void xtrskip(char *, long); |
153 | static void swap_header(struct s_spcl *); | | 153 | static void swap_header(struct s_spcl *); |
154 | static void swap_old_header(struct s_ospcl *); | | 154 | static void swap_old_header(struct s_ospcl *); |
155 | | | 155 | |
156 | //////////////////////////////////////////////////////////// | | 156 | //////////////////////////////////////////////////////////// |
157 | // thunks for type correctness | | 157 | // thunks for type correctness |
158 | | | 158 | |
159 | #define WRAP(alg) \ | | 159 | #define WRAP(alg) \ |
160 | static void \ | | 160 | static void \ |
161 | do_##alg##Init(void *ctx) \ | | 161 | do_##alg##Init(void *ctx) \ |
162 | { \ | | 162 | { \ |
163 | alg##Init(ctx); \ | | 163 | alg##Init(ctx); \ |
164 | } \ | | 164 | } \ |
165 | \ | | 165 | \ |
166 | static void \ | | 166 | static void \ |
167 | do_##alg##Update(union digest_context *ctx, \ | | 167 | do_##alg##Update(union digest_context *ctx, \ |
168 | const void *buf, unsigned len) \ | | 168 | const void *buf, unsigned len) \ |
169 | { \ | | 169 | { \ |
170 | alg##Update(&ctx->dc_##alg, buf, len); \ | | 170 | alg##Update(&ctx->dc_##alg, buf, len); \ |
171 | } \ | | 171 | } \ |
172 | \ | | 172 | \ |
173 | static char * \ | | 173 | static char * \ |
174 | do_##alg##End(void *ctx, char *str) \ | | 174 | do_##alg##End(void *ctx, char *str) \ |
175 | { \ | | 175 | { \ |
176 | return alg##End(ctx, str); \ | | 176 | return alg##End(ctx, str); \ |
177 | } | | 177 | } |
178 | | | 178 | |
179 | WRAP(MD5); | | 179 | WRAP(MD5); |
180 | WRAP(SHA1); | | 180 | WRAP(SHA1); |
181 | WRAP(RMD160); | | 181 | WRAP(RMD160); |
182 | | | 182 | |
183 | static const struct digest_desc digest_descs[] = { | | 183 | static const struct digest_desc digest_descs[] = { |
184 | { "MD5", | | 184 | { "MD5", |
185 | do_MD5Init, | | 185 | do_MD5Init, |
186 | do_MD5Update, | | 186 | do_MD5Update, |
187 | do_MD5End, }, | | 187 | do_MD5End, }, |
188 | { "SHA1", | | 188 | { "SHA1", |
189 | do_SHA1Init, | | 189 | do_SHA1Init, |
190 | do_SHA1Update, | | 190 | do_SHA1Update, |
191 | do_SHA1End, }, | | 191 | do_SHA1End, }, |
192 | { "RMD160", | | 192 | { "RMD160", |
193 | do_RMD160Init, | | 193 | do_RMD160Init, |
194 | do_RMD160Update, | | 194 | do_RMD160Update, |
195 | do_RMD160End, }, | | 195 | do_RMD160End, }, |
196 | { .dd_name = NULL }, | | 196 | { .dd_name = NULL }, |
197 | }; | | 197 | }; |
198 | | | 198 | |
199 | //////////////////////////////////////////////////////////// | | 199 | //////////////////////////////////////////////////////////// |
200 | | | 200 | |
201 | const struct digest_desc * | | 201 | const struct digest_desc * |
202 | digest_lookup(const char *name) | | 202 | digest_lookup(const char *name) |
203 | { | | 203 | { |
204 | const struct digest_desc *dd; | | 204 | const struct digest_desc *dd; |
205 | | | 205 | |
206 | for (dd = digest_descs; dd->dd_name != NULL; dd++) | | 206 | for (dd = digest_descs; dd->dd_name != NULL; dd++) |
207 | if (strcasecmp(dd->dd_name, name) == 0) | | 207 | if (strcasecmp(dd->dd_name, name) == 0) |
208 | return (dd); | | 208 | return (dd); |
209 | | | 209 | |
210 | return (NULL); | | 210 | return (NULL); |
211 | } | | 211 | } |
212 | | | 212 | |
213 | /* | | 213 | /* |
214 | * Set up an input source | | 214 | * Set up an input source |
215 | */ | | 215 | */ |
216 | void | | 216 | void |
217 | setinput(const char *source) | | 217 | setinput(const char *source) |
218 | { | | 218 | { |
219 | char *cp; | | 219 | char *cp; |
220 | FLUSHTAPEBUF(); | | 220 | FLUSHTAPEBUF(); |
221 | if (bflag) | | 221 | if (bflag) |
222 | newtapebuf(ntrec); | | 222 | newtapebuf(ntrec); |
223 | else | | 223 | else |
224 | newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC); | | 224 | newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC); |
225 | terminal = stdin; | | 225 | terminal = stdin; |
226 | | | 226 | |
227 | #ifdef RRESTORE | | 227 | #ifdef RRESTORE |
228 | if ((cp = strchr(source, ':')) != NULL) { | | 228 | if ((cp = strchr(source, ':')) != NULL) { |
229 | host = source; | | 229 | host = source; |
230 | /* Ok, because const strings don't have : */ | | 230 | /* Ok, because const strings don't have : */ |
231 | *cp++ = '\0'; | | 231 | *cp++ = '\0'; |
232 | source = cp; | | 232 | source = cp; |
233 | if (rmthost(host) == 0) | | 233 | if (rmthost(host) == 0) |
234 | exit(1); | | 234 | exit(1); |
235 | } else | | 235 | } else |
236 | #endif | | 236 | #endif |
237 | if (strcmp(source, "-") == 0) { | | 237 | if (strcmp(source, "-") == 0) { |
238 | /* | | 238 | /* |
239 | * Since input is coming from a pipe we must establish | | 239 | * Since input is coming from a pipe we must establish |
240 | * our own connection to the terminal. | | 240 | * our own connection to the terminal. |
241 | */ | | 241 | */ |
242 | terminal = fopen(_PATH_TTY, "r"); | | 242 | terminal = fopen(_PATH_TTY, "r"); |
243 | if (terminal == NULL) { | | 243 | if (terminal == NULL) { |
244 | (void)fprintf(stderr, "cannot open %s: %s\n", | | 244 | (void)fprintf(stderr, "cannot open %s: %s\n", |
245 | _PATH_TTY, strerror(errno)); | | 245 | _PATH_TTY, strerror(errno)); |
246 | terminal = fopen(_PATH_DEVNULL, "r"); | | 246 | terminal = fopen(_PATH_DEVNULL, "r"); |
247 | if (terminal == NULL) { | | 247 | if (terminal == NULL) { |
248 | (void)fprintf(stderr, "cannot open %s: %s\n", | | 248 | (void)fprintf(stderr, "cannot open %s: %s\n", |
249 | _PATH_DEVNULL, strerror(errno)); | | 249 | _PATH_DEVNULL, strerror(errno)); |
250 | exit(1); | | 250 | exit(1); |
251 | } | | 251 | } |
252 | } | | 252 | } |
253 | pipein++; | | 253 | pipein++; |
254 | } | | 254 | } |
255 | (void) strcpy(magtape, source); | | 255 | (void) strcpy(magtape, source); |
256 | } | | 256 | } |
257 | | | 257 | |
258 | void | | 258 | void |
259 | newtapebuf(long size) | | 259 | newtapebuf(long size) |
260 | { | | 260 | { |
261 | static int tapebufsize = -1; | | 261 | static int tapebufsize = -1; |
262 | | | 262 | |
263 | ntrec = size; | | 263 | ntrec = size; |
264 | if (size <= tapebufsize) | | 264 | if (size <= tapebufsize) |
265 | return; | | 265 | return; |
266 | if (tapebuf != NULL) | | 266 | if (tapebuf != NULL) |
267 | free(tapebuf); | | 267 | free(tapebuf); |
268 | tapebuf = malloc(size * TP_BSIZE); | | 268 | tapebuf = malloc(size * TP_BSIZE); |
269 | if (tapebuf == NULL) { | | 269 | if (tapebuf == NULL) { |
270 | fprintf(stderr, "Cannot allocate space for tape buffer\n"); | | 270 | fprintf(stderr, "Cannot allocate space for tape buffer\n"); |
271 | exit(1); | | 271 | exit(1); |
272 | } | | 272 | } |
273 | tapebufsize = size; | | 273 | tapebufsize = size; |
274 | } | | 274 | } |
275 | | | 275 | |
276 | /* | | 276 | /* |
277 | * Verify that the tape drive can be accessed and | | 277 | * Verify that the tape drive can be accessed and |
278 | * that it actually is a dump tape. | | 278 | * that it actually is a dump tape. |
279 | */ | | 279 | */ |
280 | void | | 280 | void |
281 | setup(void) | | 281 | setup(void) |
282 | { | | 282 | { |
283 | int i, j, *ip; | | 283 | int i, j, *ip; |
284 | struct stat stbuf; | | 284 | struct stat stbuf; |
285 | | | 285 | |
286 | vprintf(stdout, "Verify tape and initialize maps\n"); | | 286 | vprintf(stdout, "Verify tape and initialize maps\n"); |
287 | #ifdef RRESTORE | | 287 | #ifdef RRESTORE |
288 | if (host) | | 288 | if (host) |
289 | mt = rmtopen(magtape, 0, 0); | | 289 | mt = rmtopen(magtape, 0, 0); |
290 | else | | 290 | else |
291 | #endif | | 291 | #endif |
292 | if (pipein) | | 292 | if (pipein) |
293 | mt = 0; | | 293 | mt = 0; |
294 | else | | 294 | else |
295 | mt = open(magtape, O_RDONLY, 0); | | 295 | mt = open(magtape, O_RDONLY, 0); |
296 | if (mt < 0) { | | 296 | if (mt < 0) { |
297 | fprintf(stderr, "%s: %s\n", magtape, strerror(errno)); | | 297 | fprintf(stderr, "%s: %s\n", magtape, strerror(errno)); |
298 | exit(1); | | 298 | exit(1); |
299 | } | | 299 | } |
300 | volno = 1; | | 300 | volno = 1; |
301 | setdumpnum(); | | 301 | setdumpnum(); |
302 | FLUSHTAPEBUF(); | | 302 | FLUSHTAPEBUF(); |
303 | if (!pipein && !bflag) | | 303 | if (!pipein && !bflag) |
304 | findtapeblksize(); | | 304 | findtapeblksize(); |
305 | if (gethead(&spcl) == FAIL) { | | 305 | if (gethead(&spcl) == FAIL) { |
306 | blkcnt--; /* push back this block */ | | 306 | blkcnt--; /* push back this block */ |
307 | blksread--; | | 307 | blksread--; |
308 | tpblksread--; | | 308 | tpblksread--; |
309 | cvtflag++; | | 309 | cvtflag++; |
310 | if (gethead(&spcl) == FAIL) { | | 310 | if (gethead(&spcl) == FAIL) { |
311 | fprintf(stderr, "Tape is not a dump tape\n"); | | 311 | fprintf(stderr, "Tape is not a dump tape\n"); |
312 | exit(1); | | 312 | exit(1); |
313 | } | | 313 | } |
314 | fprintf(stderr, "Converting to new file system format.\n"); | | 314 | fprintf(stderr, "Converting to new file system format.\n"); |
315 | } | | 315 | } |
316 | if (pipein) { | | 316 | if (pipein) { |
317 | endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : | | 317 | endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : |
318 | FS_UFS2_MAGIC; | | 318 | FS_UFS2_MAGIC; |
319 | endoftapemark.s_spcl.c_type = TS_END; | | 319 | endoftapemark.s_spcl.c_type = TS_END; |
320 | ip = (int *)&endoftapemark; | | 320 | ip = (int *)&endoftapemark; |
321 | j = sizeof(union u_spcl) / sizeof(int); | | 321 | j = sizeof(union u_spcl) / sizeof(int); |
322 | i = 0; | | 322 | i = 0; |
323 | do | | 323 | do |
324 | i += *ip++; | | 324 | i += *ip++; |
325 | while (--j); | | 325 | while (--j); |
326 | endoftapemark.s_spcl.c_checksum = CHECKSUM - i; | | 326 | endoftapemark.s_spcl.c_checksum = CHECKSUM - i; |
327 | } | | 327 | } |
328 | if (vflag || command == 't') | | 328 | if (vflag || command == 't') |
329 | printdumpinfo(); | | 329 | printdumpinfo(); |
330 | dumptime = spcl.c_ddate; | | 330 | dumptime = spcl.c_ddate; |
331 | dumpdate = spcl.c_date; | | 331 | dumpdate = spcl.c_date; |
332 | if (stat(".", &stbuf) < 0) { | | 332 | if (stat(".", &stbuf) < 0) { |
333 | fprintf(stderr, "cannot stat .: %s\n", strerror(errno)); | | 333 | fprintf(stderr, "cannot stat .: %s\n", strerror(errno)); |
334 | exit(1); | | 334 | exit(1); |
335 | } | | 335 | } |
336 | if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE) | | 336 | if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE) |
337 | fssize = stbuf.st_blksize; | | 337 | fssize = stbuf.st_blksize; |
338 | if (((fssize - 1) & fssize) != 0) { | | 338 | if (((fssize - 1) & fssize) != 0) { |
339 | fprintf(stderr, "bad block size %d\n", fssize); | | 339 | fprintf(stderr, "bad block size %d\n", fssize); |
340 | exit(1); | | 340 | exit(1); |
341 | } | | 341 | } |
342 | if (spcl.c_volume != 1) { | | 342 | if (spcl.c_volume != 1) { |
343 | fprintf(stderr, "Tape is not volume 1 of the dump\n"); | | 343 | fprintf(stderr, "Tape is not volume 1 of the dump\n"); |
344 | exit(1); | | 344 | exit(1); |
345 | } | | 345 | } |
346 | if (gethead(&spcl) == FAIL) { | | 346 | if (gethead(&spcl) == FAIL) { |
347 | dprintf(stdout, "header read failed at %d blocks\n", blksread); | | 347 | dprintf(stdout, "header read failed at %d blocks\n", blksread); |
348 | panic("no header after volume mark!\n"); | | 348 | panic("no header after volume mark!\n"); |
349 | } | | 349 | } |
350 | findinode(&spcl); | | 350 | findinode(&spcl); |
351 | if (spcl.c_type != TS_CLRI) { | | 351 | if (spcl.c_type != TS_CLRI) { |
352 | fprintf(stderr, "Cannot find file removal list\n"); | | 352 | fprintf(stderr, "Cannot find file removal list\n"); |
353 | exit(1); | | 353 | exit(1); |
354 | } | | 354 | } |
355 | getbitmap(&usedinomap); | | 355 | getbitmap(&usedinomap); |
356 | getbitmap(&dumpmap); | | 356 | getbitmap(&dumpmap); |
357 | /* | | 357 | /* |
358 | * If there may be whiteout entries on the tape, pretend that the | | 358 | * If there may be whiteout entries on the tape, pretend that the |
359 | * whiteout inode exists, so that the whiteout entries can be | | 359 | * whiteout inode exists, so that the whiteout entries can be |
360 | * extracted. | | 360 | * extracted. |
361 | */ | | 361 | */ |
362 | if (oldinofmt == 0) | | 362 | if (oldinofmt == 0) |
363 | SETINO(UFS_WINO, dumpmap); | | 363 | SETINO(UFS_WINO, dumpmap); |
364 | } | | 364 | } |
365 | | | 365 | |
366 | /* | | 366 | /* |
367 | * Prompt user to load a new dump volume. | | 367 | * Prompt user to load a new dump volume. |
368 | * "Nextvol" is the next suggested volume to use. | | 368 | * "Nextvol" is the next suggested volume to use. |
369 | * This suggested volume is enforced when doing full | | 369 | * This suggested volume is enforced when doing full |
370 | * or incremental restores, but can be overrridden by | | 370 | * or incremental restores, but can be overrridden by |
371 | * the user when only extracting a subset of the files. | | 371 | * the user when only extracting a subset of the files. |
372 | */ | | 372 | */ |
373 | void | | 373 | void |
374 | getvol(int nextvol) | | 374 | getvol(int nextvol) |
375 | { | | 375 | { |
376 | int newvol, savecnt, wantnext, i; | | 376 | int newvol, savecnt, wantnext, i; |
377 | union u_spcl tmpspcl; | | 377 | union u_spcl tmpspcl; |
378 | # define tmpbuf tmpspcl.s_spcl | | 378 | # define tmpbuf tmpspcl.s_spcl |
379 | char buf[TP_BSIZE]; | | 379 | char buf[TP_BSIZE]; |
380 | | | 380 | |
381 | newvol = savecnt = wantnext = 0; | | 381 | newvol = savecnt = wantnext = 0; |
382 | if (nextvol == 1) { | | 382 | if (nextvol == 1) { |
383 | tapesread = 0; | | 383 | tapesread = 0; |
384 | gettingfile = 0; | | 384 | gettingfile = 0; |
385 | } | | 385 | } |
386 | if (pipein) { | | 386 | if (pipein) { |
387 | if (nextvol != 1) | | 387 | if (nextvol != 1) |
388 | panic("Changing volumes on pipe input?\n"); | | 388 | panic("Changing volumes on pipe input?\n"); |
389 | if (volno == 1) | | 389 | if (volno == 1) |
390 | return; | | 390 | return; |
391 | goto gethdr; | | 391 | goto gethdr; |
392 | } | | 392 | } |
393 | savecnt = blksread; | | 393 | savecnt = blksread; |
394 | again: | | 394 | again: |
395 | if (pipein) | | 395 | if (pipein) |
396 | exit(1); /* pipes do not get a second chance */ | | 396 | exit(1); /* pipes do not get a second chance */ |
397 | if (command == 'R' || command == 'r' || curfile.action != SKIP) { | | 397 | if (command == 'R' || command == 'r' || curfile.action != SKIP) { |
398 | newvol = nextvol; | | 398 | newvol = nextvol; |
399 | wantnext = 1; | | 399 | wantnext = 1; |
400 | } else { | | 400 | } else { |
401 | newvol = 0; | | 401 | newvol = 0; |
402 | wantnext = 0; | | 402 | wantnext = 0; |
403 | } | | 403 | } |
404 | while (newvol <= 0) { | | 404 | while (newvol <= 0) { |
405 | if (tapesread == 0) { | | 405 | if (tapesread == 0) { |
406 | fprintf(stderr, "%s%s%s%s%s", | | 406 | fprintf(stderr, "%s%s%s%s%s", |
407 | "You have not read any tapes yet.\n", | | 407 | "You have not read any tapes yet.\n", |
408 | "Unless you know which volume your", | | 408 | "Unless you know which volume your", |
409 | " file(s) are on you should start\n", | | 409 | " file(s) are on you should start\n", |
410 | "with the last volume and work", | | 410 | "with the last volume and work", |
411 | " towards the first.\n"); | | 411 | " towards the first.\n"); |
412 | fprintf(stderr, | | 412 | fprintf(stderr, |
413 | "(Use 1 for the first volume/tape, etc.)\n"); | | 413 | "(Use 1 for the first volume/tape, etc.)\n"); |
414 | } else { | | 414 | } else { |
415 | fprintf(stderr, "You have read volumes"); | | 415 | fprintf(stderr, "You have read volumes"); |
416 | strcpy(buf, ": "); | | 416 | strcpy(buf, ": "); |
417 | for (i = 1; i < 32; i++) | | 417 | for (i = 1; i < 32; i++) |
418 | if (tapesread & (1 << i)) { | | 418 | if (tapesread & (1 << i)) { |
419 | fprintf(stderr, "%s%d", buf, i); | | 419 | fprintf(stderr, "%s%d", buf, i); |
420 | strcpy(buf, ", "); | | 420 | strcpy(buf, ", "); |
421 | } | | 421 | } |
422 | fprintf(stderr, "\n"); | | 422 | fprintf(stderr, "\n"); |
423 | } | | 423 | } |
424 | do { | | 424 | do { |
425 | fprintf(stderr, "Specify next volume #: "); | | 425 | fprintf(stderr, "Specify next volume #: "); |
426 | (void) fflush(stderr); | | 426 | (void) fflush(stderr); |
427 | (void) fgets(buf, BUFSIZ, terminal); | | 427 | (void) fgets(buf, BUFSIZ, terminal); |
428 | } while (!feof(terminal) && buf[0] == '\n'); | | 428 | } while (!feof(terminal) && buf[0] == '\n'); |
429 | if (feof(terminal)) | | 429 | if (feof(terminal)) |
430 | exit(1); | | 430 | exit(1); |
431 | newvol = atoi(buf); | | 431 | newvol = atoi(buf); |
432 | if (newvol <= 0) { | | 432 | if (newvol <= 0) { |
433 | fprintf(stderr, | | 433 | fprintf(stderr, |
434 | "Volume numbers are positive numerics\n"); | | 434 | "Volume numbers are positive numerics\n"); |
435 | } | | 435 | } |
436 | } | | 436 | } |
437 | if (newvol == volno) { | | 437 | if (newvol == volno) { |
438 | tapesread |= 1 << volno; | | 438 | tapesread |= 1 << volno; |
439 | return; | | 439 | return; |
440 | } | | 440 | } |
441 | closemt(); | | 441 | closemt(); |
442 | fprintf(stderr, "Mount tape volume %d\n", newvol); | | 442 | fprintf(stderr, "Mount tape volume %d\n", newvol); |
443 | fprintf(stderr, "Enter ``none'' if there are no more tapes\n"); | | 443 | fprintf(stderr, "Enter ``none'' if there are no more tapes\n"); |
444 | fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape); | | 444 | fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape); |
445 | (void) fflush(stderr); | | 445 | (void) fflush(stderr); |
446 | (void) fgets(buf, BUFSIZ, terminal); | | 446 | (void) fgets(buf, BUFSIZ, terminal); |
447 | if (feof(terminal)) | | 447 | if (feof(terminal)) |
448 | exit(1); | | 448 | exit(1); |
449 | if (!strcmp(buf, "none\n")) { | | 449 | if (!strcmp(buf, "none\n")) { |
450 | terminateinput(); | | 450 | terminateinput(); |
451 | return; | | 451 | return; |
452 | } | | 452 | } |
453 | if (buf[0] != '\n') { | | 453 | if (buf[0] != '\n') { |
454 | (void) strcpy(magtape, buf); | | 454 | (void) strcpy(magtape, buf); |
455 | magtape[strlen(magtape) - 1] = '\0'; | | 455 | magtape[strlen(magtape) - 1] = '\0'; |
456 | } | | 456 | } |
457 | #ifdef RRESTORE | | 457 | #ifdef RRESTORE |
458 | if (host) | | 458 | if (host) |
459 | mt = rmtopen(magtape, 0, 0); | | 459 | mt = rmtopen(magtape, 0, 0); |
460 | else | | 460 | else |
461 | #endif | | 461 | #endif |
462 | mt = open(magtape, O_RDONLY, 0); | | 462 | mt = open(magtape, O_RDONLY, 0); |
463 | | | 463 | |
464 | if (mt == -1) { | | 464 | if (mt == -1) { |
465 | fprintf(stderr, "Cannot open %s\n", magtape); | | 465 | fprintf(stderr, "Cannot open %s\n", magtape); |
466 | volno = -1; | | 466 | volno = -1; |
467 | goto again; | | 467 | goto again; |
468 | } | | 468 | } |
469 | gethdr: | | 469 | gethdr: |
470 | volno = newvol; | | 470 | volno = newvol; |
471 | setdumpnum(); | | 471 | setdumpnum(); |
472 | FLUSHTAPEBUF(); | | 472 | FLUSHTAPEBUF(); |
473 | if (gethead(&tmpbuf) == FAIL) { | | 473 | if (gethead(&tmpbuf) == FAIL) { |
474 | dprintf(stdout, "header read failed at %d blocks\n", blksread); | | 474 | dprintf(stdout, "header read failed at %d blocks\n", blksread); |
475 | fprintf(stderr, "tape is not dump tape\n"); | | 475 | fprintf(stderr, "tape is not dump tape\n"); |
476 | volno = 0; | | 476 | volno = 0; |
477 | goto again; | | 477 | goto again; |
478 | } | | 478 | } |
479 | if (tmpbuf.c_volume != volno) { | | 479 | if (tmpbuf.c_volume != volno) { |
480 | fprintf(stderr, | | 480 | fprintf(stderr, |
481 | "Volume mismatch: expecting %d, tape header claims it is %d\n", | | 481 | "Volume mismatch: expecting %d, tape header claims it is %d\n", |
482 | volno, tmpbuf.c_volume); | | 482 | volno, tmpbuf.c_volume); |
483 | volno = 0; | | 483 | volno = 0; |
484 | goto again; | | 484 | goto again; |
485 | } | | 485 | } |
486 | if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) { | | 486 | if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) { |
487 | time_t ttime = tmpbuf.c_date; | | 487 | time_t ttime = tmpbuf.c_date; |
488 | fprintf(stderr, "Wrong dump date\n\tgot: %s", | | 488 | fprintf(stderr, "Wrong dump date\n\tgot: %s", |
489 | ctime(&ttime)); | | 489 | ctime(&ttime)); |
490 | fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); | | 490 | fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); |
491 | volno = 0; | | 491 | volno = 0; |
492 | goto again; | | 492 | goto again; |
493 | } | | 493 | } |
494 | tapesread |= 1 << volno; | | 494 | tapesread |= 1 << volno; |
495 | blksread = savecnt; | | 495 | blksread = savecnt; |
496 | /* | | 496 | /* |
497 | * If continuing from the previous volume, skip over any | | 497 | * If continuing from the previous volume, skip over any |
498 | * blocks read already at the end of the previous volume. | | 498 | * blocks read already at the end of the previous volume. |
499 | * | | 499 | * |
500 | * If coming to this volume at random, skip to the beginning | | 500 | * If coming to this volume at random, skip to the beginning |
501 | * of the next record. | | 501 | * of the next record. |
502 | */ | | 502 | */ |
503 | dprintf(stdout, "read %ld recs, tape starts with %ld\n", | | 503 | dprintf(stdout, "read %ld recs, tape starts with %ld\n", |
504 | (long)tpblksread, (long)tmpbuf.c_firstrec); | | 504 | (long)tpblksread, (long)tmpbuf.c_firstrec); |
505 | if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) { | | 505 | if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) { |
506 | if (!wantnext) { | | 506 | if (!wantnext) { |
507 | tpblksread = tmpbuf.c_firstrec; | | 507 | tpblksread = tmpbuf.c_firstrec; |
508 | for (i = tmpbuf.c_count; i > 0; i--) | | 508 | for (i = tmpbuf.c_count; i > 0; i--) |
509 | readtape(buf); | | 509 | readtape(buf); |
510 | } else if (tmpbuf.c_firstrec > 0 && | | 510 | } else if (tmpbuf.c_firstrec > 0 && |
511 | tmpbuf.c_firstrec < tpblksread - 1) { | | 511 | tmpbuf.c_firstrec < tpblksread - 1) { |
512 | /* | | 512 | /* |
513 | * -1 since we've read the volume header | | 513 | * -1 since we've read the volume header |
514 | */ | | 514 | */ |
515 | i = tpblksread - tmpbuf.c_firstrec - 1; | | 515 | i = tpblksread - tmpbuf.c_firstrec - 1; |
516 | dprintf(stderr, "Skipping %d duplicate record%s.\n", | | 516 | dprintf(stderr, "Skipping %d duplicate record%s.\n", |
517 | i, i > 1 ? "s" : ""); | | 517 | i, i > 1 ? "s" : ""); |
518 | while (--i >= 0) | | 518 | while (--i >= 0) |
519 | readtape(buf); | | 519 | readtape(buf); |
520 | } | | 520 | } |
521 | } | | 521 | } |
522 | if (curfile.action == USING) { | | 522 | if (curfile.action == USING) { |
523 | if (volno == 1) | | 523 | if (volno == 1) |
524 | panic("active file into volume 1\n"); | | 524 | panic("active file into volume 1\n"); |
525 | return; | | 525 | return; |
526 | } | | 526 | } |
527 | /* | | 527 | /* |
528 | * Skip up to the beginning of the next record | | 528 | * Skip up to the beginning of the next record |
529 | */ | | 529 | */ |
530 | if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) | | 530 | if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) |
531 | for (i = tmpbuf.c_count; i > 0; i--) | | 531 | for (i = tmpbuf.c_count; i > 0; i--) |
532 | readtape(buf); | | 532 | readtape(buf); |
533 | (void) gethead(&spcl); | | 533 | (void) gethead(&spcl); |
534 | findinode(&spcl); | | 534 | findinode(&spcl); |
535 | if (gettingfile) { | | 535 | if (gettingfile) { |
536 | gettingfile = 0; | | 536 | gettingfile = 0; |
537 | longjmp(restart, 1); | | 537 | longjmp(restart, 1); |
538 | } | | 538 | } |
539 | } | | 539 | } |
540 | | | 540 | |
541 | /* | | 541 | /* |
542 | * Handle unexpected EOF. | | 542 | * Handle unexpected EOF. |
543 | */ | | 543 | */ |
544 | static void | | 544 | static void |
545 | terminateinput(void) | | 545 | terminateinput(void) |
546 | { | | 546 | { |
547 | | | 547 | |
548 | if (gettingfile && curfile.action == USING) { | | 548 | if (gettingfile && curfile.action == USING) { |
549 | printf("Warning: %s %s\n", | | 549 | printf("Warning: %s %s\n", |
550 | "End-of-input encountered while extracting", curfile.name); | | 550 | "End-of-input encountered while extracting", curfile.name); |
551 | } | | 551 | } |
552 | curfile.name = "<name unknown>"; | | 552 | curfile.name = "<name unknown>"; |
553 | curfile.action = UNKNOWN; | | 553 | curfile.action = UNKNOWN; |
554 | curfile.mode = 0; | | 554 | curfile.mode = 0; |
555 | curfile.ino = maxino; | | 555 | curfile.ino = maxino; |
556 | if (gettingfile) { | | 556 | if (gettingfile) { |
557 | gettingfile = 0; | | 557 | gettingfile = 0; |
558 | longjmp(restart, 1); | | 558 | longjmp(restart, 1); |
559 | } | | 559 | } |
560 | } | | 560 | } |
561 | | | 561 | |
562 | /* | | 562 | /* |
563 | * handle multiple dumps per tape by skipping forward to the | | 563 | * handle multiple dumps per tape by skipping forward to the |
564 | * appropriate one. | | 564 | * appropriate one. |
565 | */ | | 565 | */ |
566 | static void | | 566 | static void |
567 | setdumpnum(void) | | 567 | setdumpnum(void) |
568 | { | | 568 | { |
569 | struct mtop tcom; | | 569 | struct mtop tcom; |
570 | | | 570 | |
571 | if (dumpnum == 1 || volno != 1) | | 571 | if (dumpnum == 1 || volno != 1) |
572 | return; | | 572 | return; |
573 | if (pipein) { | | 573 | if (pipein) { |
574 | fprintf(stderr, "Cannot have multiple dumps on pipe input\n"); | | 574 | fprintf(stderr, "Cannot have multiple dumps on pipe input\n"); |
575 | exit(1); | | 575 | exit(1); |
576 | } | | 576 | } |
577 | tcom.mt_op = MTFSF; | | 577 | tcom.mt_op = MTFSF; |
578 | tcom.mt_count = dumpnum - 1; | | 578 | tcom.mt_count = dumpnum - 1; |
579 | #ifdef RRESTORE | | 579 | #ifdef RRESTORE |
580 | if (host) | | 580 | if (host) |
581 | rmtioctl(MTFSF, dumpnum - 1); | | 581 | rmtioctl(MTFSF, dumpnum - 1); |
582 | else | | 582 | else |
583 | #endif | | 583 | #endif |
584 | if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0) | | 584 | if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0) |
585 | fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno)); | | 585 | fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno)); |
586 | } | | 586 | } |
587 | | | 587 | |
588 | void | | 588 | void |
589 | printdumpinfo(void) | | 589 | printdumpinfo(void) |
590 | { | | 590 | { |
591 | time_t ttime; | | 591 | time_t ttime; |
592 | | | 592 | |
593 | ttime = spcl.c_date; | | 593 | ttime = spcl.c_date; |
594 | fprintf(stdout, "Dump date: %s", ctime(&ttime)); | | 594 | fprintf(stdout, "Dump date: %s", ctime(&ttime)); |
595 | ttime = spcl.c_ddate; | | 595 | ttime = spcl.c_ddate; |
596 | fprintf(stdout, "Dumped from: %s", | | 596 | fprintf(stdout, "Dumped from: %s", |
597 | (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&ttime)); | | 597 | (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&ttime)); |
598 | fprintf(stderr, "Level %d dump of %s on %s:%s\n", | | 598 | fprintf(stderr, "Level %d dump of %s on %s:%s\n", |
599 | spcl.c_level, spcl.c_filesys, | | 599 | spcl.c_level, spcl.c_filesys, |
600 | *spcl.c_host? spcl.c_host: "[unknown]", spcl.c_dev); | | 600 | *spcl.c_host? spcl.c_host: "[unknown]", spcl.c_dev); |
601 | fprintf(stderr, "Label: %s\n", spcl.c_label); | | 601 | fprintf(stderr, "Label: %s\n", spcl.c_label); |
602 | | | 602 | |
603 | if (Mtreefile) { | | 603 | if (Mtreefile) { |
604 | ttime = spcl.c_date; | | 604 | ttime = spcl.c_date; |
605 | fprintf(Mtreefile, "#Dump date: %s", ctime(&ttime)); | | 605 | fprintf(Mtreefile, "#Dump date: %s", ctime(&ttime)); |
606 | ttime = spcl.c_ddate; | | 606 | ttime = spcl.c_ddate; |
607 | fprintf(Mtreefile, "#Dumped from: %s", | | 607 | fprintf(Mtreefile, "#Dumped from: %s", |
608 | (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&ttime)); | | 608 | (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&ttime)); |
609 | fprintf(Mtreefile, "#Level %d dump of %s on %s:%s\n", | | 609 | fprintf(Mtreefile, "#Level %d dump of %s on %s:%s\n", |
610 | spcl.c_level, spcl.c_filesys, | | 610 | spcl.c_level, spcl.c_filesys, |
611 | *spcl.c_host? spcl.c_host: "[unknown]", spcl.c_dev); | | 611 | *spcl.c_host? spcl.c_host: "[unknown]", spcl.c_dev); |
612 | fprintf(Mtreefile, "#Label: %s\n", spcl.c_label); | | 612 | fprintf(Mtreefile, "#Label: %s\n", spcl.c_label); |
613 | fprintf(Mtreefile, "/set uname=root gname=wheel\n"); | | 613 | fprintf(Mtreefile, "/set uname=root gname=wheel\n"); |
614 | if (ferror(Mtreefile)) | | 614 | if (ferror(Mtreefile)) |
615 | err(1, "error writing to mtree file"); | | 615 | err(1, "error writing to mtree file"); |
616 | } | | 616 | } |
617 | } | | 617 | } |
618 | | | 618 | |
619 | int | | 619 | int |
620 | extractfile(char *name) | | 620 | extractfile(char *name) |
621 | { | | 621 | { |
622 | char dbuffer[DIGEST_BUFFER_SIZE]; | | 622 | char dbuffer[DIGEST_BUFFER_SIZE]; |
623 | int flags; | | 623 | int flags; |
624 | uid_t uid; | | 624 | uid_t uid; |
625 | gid_t gid; | | 625 | gid_t gid; |
626 | mode_t mode; | | 626 | mode_t mode; |
627 | struct timespec mtimep[2], ctimep[2]; | | 627 | struct timespec mtimep[2], ctimep[2]; |
628 | struct entry *ep; | | 628 | struct entry *ep; |
629 | int setbirth; | | 629 | int setbirth; |
630 | | | 630 | |
631 | curfile.name = name; | | 631 | curfile.name = name; |
632 | curfile.action = USING; | | 632 | curfile.action = USING; |
633 | mtimep[0].tv_sec = curfile.atime_sec; | | 633 | mtimep[0].tv_sec = curfile.atime_sec; |
634 | mtimep[0].tv_nsec = curfile.atime_nsec; | | 634 | mtimep[0].tv_nsec = curfile.atime_nsec; |
635 | mtimep[1].tv_sec = curfile.mtime_sec; | | 635 | mtimep[1].tv_sec = curfile.mtime_sec; |
636 | mtimep[1].tv_nsec = curfile.mtime_nsec; | | 636 | mtimep[1].tv_nsec = curfile.mtime_nsec; |
637 | | | 637 | |
638 | setbirth = curfile.birthtime_sec != 0; | | 638 | setbirth = curfile.birthtime_sec != 0; |
639 | | | 639 | |
640 | if (setbirth) { | | 640 | if (setbirth) { |
641 | ctimep[0].tv_sec = curfile.atime_sec; | | 641 | ctimep[0].tv_sec = curfile.atime_sec; |
642 | ctimep[0].tv_nsec = curfile.atime_nsec; | | 642 | ctimep[0].tv_nsec = curfile.atime_nsec; |
643 | ctimep[1].tv_sec = curfile.birthtime_sec; | | 643 | ctimep[1].tv_sec = curfile.birthtime_sec; |
644 | ctimep[1].tv_nsec = curfile.birthtime_nsec; | | 644 | ctimep[1].tv_nsec = curfile.birthtime_nsec; |
645 | } | | 645 | } |
646 | uid = curfile.uid; | | 646 | uid = curfile.uid; |
647 | gid = curfile.gid; | | 647 | gid = curfile.gid; |
648 | mode = curfile.mode; | | 648 | mode = curfile.mode; |
649 | flags = curfile.file_flags; | | 649 | flags = curfile.file_flags; |
650 | switch (mode & IFMT) { | | 650 | switch (mode & IFMT) { |
651 | | | 651 | |
652 | default: | | 652 | default: |
653 | fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode); | | 653 | fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode); |
654 | skipfile(); | | 654 | skipfile(); |
655 | return (FAIL); | | 655 | return (FAIL); |
656 | | | 656 | |
657 | case IFSOCK: | | 657 | case IFSOCK: |
658 | vprintf(stdout, "skipped socket %s\n", name); | | 658 | vprintf(stdout, "skipped socket %s\n", name); |
659 | skipfile(); | | 659 | skipfile(); |
660 | return (GOOD); | | 660 | return (GOOD); |
661 | | | 661 | |
662 | case IFDIR: | | 662 | case IFDIR: |
663 | if (mflag) { | | 663 | if (mflag) { |
664 | ep = lookupname(name); | | 664 | ep = lookupname(name); |
665 | if (ep == NULL || ep->e_flags & EXTRACT) | | 665 | if (ep == NULL || ep->e_flags & EXTRACT) |
666 | panic("unextracted directory %s\n", name); | | 666 | panic("unextracted directory %s\n", name); |
667 | skipfile(); | | 667 | skipfile(); |
668 | return (GOOD); | | 668 | return (GOOD); |
669 | } | | 669 | } |
670 | vprintf(stdout, "extract file %s\n", name); | | 670 | vprintf(stdout, "extract file %s\n", name); |
671 | return (genliteraldir(name, curfile.ino)); | | 671 | return (genliteraldir(name, curfile.ino)); |
672 | | | 672 | |
673 | case IFLNK: | | 673 | case IFLNK: |
674 | lnkbuf[0] = '\0'; | | 674 | lnkbuf[0] = '\0'; |
675 | pathlen = 0; | | 675 | pathlen = 0; |
676 | getfile(xtrlnkfile, xtrlnkskip); | | 676 | getfile(xtrlnkfile, xtrlnkskip); |
677 | if (pathlen == 0) { | | 677 | if (pathlen == 0) { |
678 | vprintf(stdout, | | 678 | vprintf(stdout, |
679 | "%s: zero length symbolic link (ignored)\n", name); | | 679 | "%s: zero length symbolic link (ignored)\n", name); |
680 | return (GOOD); | | 680 | return (GOOD); |
681 | } | | 681 | } |
682 | if (uflag) | | 682 | if (uflag) |
683 | (void) unlink(name); | | 683 | (void) unlink(name); |
684 | if (linkit(lnkbuf, name, SYMLINK) == GOOD) { | | 684 | if (linkit(lnkbuf, name, SYMLINK) == GOOD) { |
685 | if (setbirth) | | 685 | if (setbirth) |
686 | (void) lutimens(name, ctimep); | | 686 | (void) lutimens(name, ctimep); |
687 | (void) lutimens(name, mtimep); | | 687 | (void) lutimens(name, mtimep); |
688 | (void) lchown(name, uid, gid); | | 688 | (void) lchown(name, uid, gid); |
689 | (void) lchmod(name, mode); | | 689 | (void) lchmod(name, mode); |
690 | if (Mtreefile) { | | 690 | if (Mtreefile) { |
691 | writemtree(name, "link", | | 691 | writemtree(name, "link", |
692 | uid, gid, mode, flags); | | 692 | uid, gid, mode, flags); |
693 | } else | | 693 | } else |
694 | (void) lchflags(name, flags); | | 694 | (void) lchflags(name, flags); |
695 | return (GOOD); | | 695 | return (GOOD); |
696 | } | | 696 | } |
697 | return (FAIL); | | 697 | return (FAIL); |
698 | | | 698 | |
699 | case IFCHR: | | 699 | case IFCHR: |
700 | case IFBLK: | | 700 | case IFBLK: |
701 | vprintf(stdout, "extract special file %s\n", name); | | 701 | vprintf(stdout, "extract special file %s\n", name); |
702 | if (Nflag) { | | 702 | if (Nflag) { |
703 | skipfile(); | | 703 | skipfile(); |
704 | return (GOOD); | | 704 | return (GOOD); |
705 | } | | 705 | } |
706 | if (uflag) | | 706 | if (uflag) |
707 | (void) unlink(name); | | 707 | (void) unlink(name); |
708 | if (mknod(name, (mode & (IFCHR | IFBLK)) | 0600, | | 708 | if (mknod(name, (mode & (IFCHR | IFBLK)) | 0600, |
709 | (int)curfile.rdev) < 0) { | | 709 | (int)curfile.rdev) < 0) { |
710 | fprintf(stderr, "%s: cannot create special file: %s\n", | | 710 | fprintf(stderr, "%s: cannot create special file: %s\n", |
711 | name, strerror(errno)); | | 711 | name, strerror(errno)); |
712 | skipfile(); | | 712 | skipfile(); |
713 | return (FAIL); | | 713 | return (FAIL); |
714 | } | | 714 | } |
715 | skipfile(); | | 715 | skipfile(); |
716 | if (setbirth) | | 716 | if (setbirth) |
717 | (void) utimens(name, ctimep); | | 717 | (void) utimens(name, ctimep); |
718 | (void) utimens(name, mtimep); | | 718 | (void) utimens(name, mtimep); |
719 | (void) chown(name, uid, gid); | | 719 | (void) chown(name, uid, gid); |
720 | (void) chmod(name, mode); | | 720 | (void) chmod(name, mode); |
721 | if (Mtreefile) { | | 721 | if (Mtreefile) { |
722 | writemtree(name, | | 722 | writemtree(name, |
723 | ((mode & (S_IFBLK | IFCHR)) == IFBLK) ? | | 723 | ((mode & (S_IFBLK | IFCHR)) == IFBLK) ? |
724 | "block" : "char", | | 724 | "block" : "char", |
725 | uid, gid, mode, flags); | | 725 | uid, gid, mode, flags); |
726 | } else | | 726 | } else |
727 | (void) chflags(name, flags); | | 727 | (void) chflags(name, flags); |
728 | return (GOOD); | | 728 | return (GOOD); |
729 | | | 729 | |
730 | case IFIFO: | | 730 | case IFIFO: |
731 | vprintf(stdout, "extract fifo %s\n", name); | | 731 | vprintf(stdout, "extract fifo %s\n", name); |
732 | if (Nflag) { | | 732 | if (Nflag) { |
733 | skipfile(); | | 733 | skipfile(); |
734 | return (GOOD); | | 734 | return (GOOD); |
735 | } | | 735 | } |
736 | if (uflag) | | 736 | if (uflag) |
737 | (void) unlink(name); | | 737 | (void) unlink(name); |
738 | if (mkfifo(name, 0600) < 0) { | | 738 | if (mkfifo(name, 0600) < 0) { |
739 | fprintf(stderr, "%s: cannot create fifo: %s\n", | | 739 | fprintf(stderr, "%s: cannot create fifo: %s\n", |
740 | name, strerror(errno)); | | 740 | name, strerror(errno)); |
741 | skipfile(); | | 741 | skipfile(); |
742 | return (FAIL); | | 742 | return (FAIL); |
743 | } | | 743 | } |
744 | skipfile(); | | 744 | skipfile(); |
745 | if (setbirth) | | 745 | if (setbirth) |
746 | (void) utimens(name, ctimep); | | 746 | (void) utimens(name, ctimep); |
747 | (void) utimens(name, mtimep); | | 747 | (void) utimens(name, mtimep); |
748 | (void) chown(name, uid, gid); | | 748 | (void) chown(name, uid, gid); |
749 | (void) chmod(name, mode); | | 749 | (void) chmod(name, mode); |
750 | if (Mtreefile) { | | 750 | if (Mtreefile) { |
751 | writemtree(name, "fifo", | | 751 | writemtree(name, "fifo", |
752 | uid, gid, mode, flags); | | 752 | uid, gid, mode, flags); |
753 | } else | | 753 | } else |
754 | (void) chflags(name, flags); | | 754 | (void) chflags(name, flags); |
755 | return (GOOD); | | 755 | return (GOOD); |
756 | | | 756 | |
757 | case IFREG: | | 757 | case IFREG: |
758 | vprintf(stdout, "extract file %s\n", name); | | 758 | vprintf(stdout, "extract file %s\n", name); |
759 | if (uflag) | | 759 | if (uflag) |
760 | (void) unlink(name); | | 760 | (void) unlink(name); |
761 | if (!Nflag && (ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, | | 761 | if (!Nflag && (ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, |
762 | 0600)) < 0) { | | 762 | 0600)) < 0) { |
763 | fprintf(stderr, "%s: cannot create file: %s\n", | | 763 | fprintf(stderr, "%s: cannot create file: %s\n", |
764 | name, strerror(errno)); | | 764 | name, strerror(errno)); |
765 | skipfile(); | | 765 | skipfile(); |
766 | return (FAIL); | | 766 | return (FAIL); |
767 | } | | 767 | } |
768 | if (Dflag) | | 768 | if (Dflag) |
769 | (*ddesc->dd_init)(&dcontext); | | 769 | (*ddesc->dd_init)(&dcontext); |
770 | getfile(xtrfile, xtrskip); | | 770 | getfile(xtrfile, xtrskip); |
771 | if (Dflag) { | | 771 | if (Dflag) { |
772 | (*ddesc->dd_end)(&dcontext, dbuffer); | | 772 | (*ddesc->dd_end)(&dcontext, dbuffer); |
773 | for (ep = lookupname(name); ep != NULL; | | 773 | for (ep = lookupname(name); ep != NULL; |
774 | ep = ep->e_links) | | 774 | ep = ep->e_links) |
775 | fprintf(stdout, "%s (%s) = %s\n", | | 775 | fprintf(stdout, "%s (%s) = %s\n", |
776 | ddesc->dd_name, myname(ep), | | 776 | ddesc->dd_name, myname(ep), |
777 | dbuffer); | | 777 | dbuffer); |
778 | } | | 778 | } |
779 | if (Nflag) | | 779 | if (Nflag) |
780 | return (GOOD); | | 780 | return (GOOD); |
781 | if (setbirth) | | 781 | if (setbirth) |
782 | (void) futimens(ofile, ctimep); | | 782 | (void) futimens(ofile, ctimep); |
783 | (void) futimens(ofile, mtimep); | | 783 | (void) futimens(ofile, mtimep); |
784 | (void) fchown(ofile, uid, gid); | | 784 | (void) fchown(ofile, uid, gid); |
785 | (void) fchmod(ofile, mode); | | 785 | (void) fchmod(ofile, mode); |
786 | if (Mtreefile) { | | 786 | if (Mtreefile) { |
787 | writemtree(name, "file", | | 787 | writemtree(name, "file", |
788 | uid, gid, mode, flags); | | 788 | uid, gid, mode, flags); |
789 | } else | | 789 | } else |
790 | (void) fchflags(ofile, flags); | | 790 | (void) fchflags(ofile, flags); |
791 | (void) close(ofile); | | 791 | (void) close(ofile); |
792 | return (GOOD); | | 792 | return (GOOD); |
793 | } | | 793 | } |
794 | /* NOTREACHED */ | | 794 | /* NOTREACHED */ |
795 | } | | 795 | } |
796 | | | 796 | |
797 | /* | | 797 | /* |
798 | * skip over bit maps on the tape | | 798 | * skip over bit maps on the tape |
799 | */ | | 799 | */ |
800 | void | | 800 | void |
801 | skipmaps(void) | | 801 | skipmaps(void) |
802 | { | | 802 | { |
803 | | | 803 | |
804 | while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI) | | 804 | while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI) |
805 | skipfile(); | | 805 | skipfile(); |
806 | } | | 806 | } |
807 | | | 807 | |
808 | /* | | 808 | /* |
809 | * skip over a file on the tape | | 809 | * skip over a file on the tape |
810 | */ | | 810 | */ |
811 | void | | 811 | void |
812 | skipfile(void) | | 812 | skipfile(void) |
813 | { | | 813 | { |
814 | | | 814 | |
815 | curfile.action = SKIP; | | 815 | curfile.action = SKIP; |
816 | getfile(xtrnull, xtrnull); | | 816 | getfile(xtrnull, xtrnull); |
817 | } | | 817 | } |
818 | | | 818 | |
819 | /* | | 819 | /* |
820 | * Extract a bitmap from the tape. | | 820 | * Extract a bitmap from the tape. |
821 | * The first bitmap sets maxino; | | 821 | * The first bitmap sets maxino; |
822 | * other bitmaps must be of same size. | | 822 | * other bitmaps must be of same size. |
823 | */ | | 823 | */ |
824 | void | | 824 | void |
825 | getbitmap(char **map) | | 825 | getbitmap(char **map) |
826 | { | | 826 | { |
827 | int i; | | 827 | int i; |
828 | size_t volatile size = spcl.c_size; | | 828 | size_t volatile size = spcl.c_size; |
829 | size_t volatile mapsize = size; | | 829 | size_t volatile mapsize = size; |
830 | char *mapptr; | | 830 | char *mapptr; |
831 | | | 831 | |
832 | curfile.action = USING; | | 832 | curfile.action = USING; |
833 | if (spcl.c_type == TS_END) | | 833 | if (spcl.c_type == TS_END) |
834 | panic("ran off end of tape\n"); | | 834 | panic("ran off end of tape\n"); |
835 | if (spcl.c_magic != FS_UFS2_MAGIC) | | 835 | if (spcl.c_magic != FS_UFS2_MAGIC) |
836 | panic("not at beginning of a file\n"); | | 836 | panic("not at beginning of a file\n"); |
837 | if (!gettingfile && setjmp(restart) != 0) | | 837 | if (!gettingfile && setjmp(restart) != 0) |
838 | return; | | 838 | return; |
839 | gettingfile++; | | 839 | gettingfile++; |
840 | mapptr = *map = malloc(size); | | 840 | mapptr = *map = malloc(size); |
841 | loop: | | 841 | loop: |
842 | if (*map == NULL) | | 842 | if (*map == NULL) |
843 | panic("no memory for %s\n", curfile.name); | | 843 | panic("no memory for %s\n", curfile.name); |
844 | for (i = 0; i < spcl.c_count && size >= TP_BSIZE; i++) { | | 844 | for (i = 0; i < spcl.c_count && size >= TP_BSIZE; i++) { |
845 | readtape(mapptr); | | 845 | readtape(mapptr); |
846 | mapptr += TP_BSIZE; | | 846 | mapptr += TP_BSIZE; |
847 | size -= TP_BSIZE; | | 847 | size -= TP_BSIZE; |
848 | } | | 848 | } |
849 | if (size != 0 || i != spcl.c_count) | | 849 | if (size != 0 || i != spcl.c_count) |
850 | panic("%s: inconsistent map size\n", curfile.name); | | 850 | panic("%s: inconsistent map size\n", curfile.name); |
851 | if (gethead(&spcl) == GOOD && spcl.c_type == TS_ADDR) { | | 851 | if (gethead(&spcl) == GOOD && spcl.c_type == TS_ADDR) { |
852 | size = spcl.c_count * TP_BSIZE; | | 852 | size = spcl.c_count * TP_BSIZE; |
853 | *map = realloc(*map, mapsize + size); | | 853 | *map = realloc(*map, mapsize + size); |
854 | mapptr = *map + mapsize; | | 854 | mapptr = *map + mapsize; |
855 | mapsize += size; | | 855 | mapsize += size; |
856 | goto loop; | | 856 | goto loop; |
857 | } | | 857 | } |
858 | if (maxino == 0) | | 858 | if (maxino == 0) |
859 | maxino = mapsize * NBBY + 1; | | 859 | maxino = mapsize * NBBY + 1; |
860 | else if (maxino != mapsize * NBBY + 1) | | 860 | else if (maxino != mapsize * NBBY + 1) |
861 | panic("%s: map size changed\n", curfile.name); | | 861 | panic("%s: map size changed\n", curfile.name); |
862 | findinode(&spcl); | | 862 | findinode(&spcl); |
863 | gettingfile = 0; | | 863 | gettingfile = 0; |
864 | } | | 864 | } |
865 | | | 865 | |
866 | /* | | 866 | /* |
867 | * Extract a file from the tape. | | 867 | * Extract a file from the tape. |
868 | * When an allocated block is found it is passed to the fill function; | | 868 | * When an allocated block is found it is passed to the fill function; |
869 | * when an unallocated block (hole) is found, a zeroed buffer is passed | | 869 | * when an unallocated block (hole) is found, a zeroed buffer is passed |
870 | * to the skip function. | | 870 | * to the skip function. |
871 | */ | | 871 | */ |
872 | void | | 872 | void |
873 | getfile(void (*fill)(char *buf, long size), | | 873 | getfile(void (*fill)(char *buf, long size), |
874 | void (*skip)(char *buf, long size)) | | 874 | void (*skip)(char *buf, long size)) |
875 | { | | 875 | { |
876 | int i; | | 876 | int i; |
877 | int volatile curblk; | | 877 | int volatile curblk; |
878 | quad_t volatile size; | | 878 | quad_t volatile size; |
879 | static char clearedbuf[MAXBSIZE]; | | 879 | static char clearedbuf[MAXBSIZE]; |
880 | char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; | | 880 | char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; |
881 | char junk[TP_BSIZE]; | | 881 | char junk[TP_BSIZE]; |
882 | | | 882 | |
883 | curblk = 0; | | 883 | curblk = 0; |
884 | size = spcl.c_size; | | 884 | size = spcl.c_size; |
885 | | | 885 | |
886 | if (spcl.c_type == TS_END) | | 886 | if (spcl.c_type == TS_END) |
887 | panic("ran off end of tape\n"); | | 887 | panic("ran off end of tape\n"); |
888 | if (spcl.c_magic != FS_UFS2_MAGIC) | | 888 | if (spcl.c_magic != FS_UFS2_MAGIC) |
889 | panic("not at beginning of a file\n"); | | 889 | panic("not at beginning of a file\n"); |
890 | if (!gettingfile && setjmp(restart) != 0) | | 890 | if (!gettingfile && setjmp(restart) != 0) |
891 | return; | | 891 | return; |
892 | gettingfile++; | | 892 | gettingfile++; |
893 | loop: | | 893 | loop: |
894 | for (i = 0; i < spcl.c_count; i++) { | | 894 | for (i = 0; i < spcl.c_count; i++) { |
895 | if (spcl.c_addr[i]) { | | 895 | if (spcl.c_addr[i]) { |
896 | readtape(&buf[curblk++][0]); | | 896 | readtape(&buf[curblk++][0]); |
897 | if ((uint32_t)curblk == fssize / TP_BSIZE) { | | 897 | if ((uint32_t)curblk == fssize / TP_BSIZE) { |
898 | (*fill)((char *)buf, (long)(size > TP_BSIZE ? | | 898 | (*fill)((char *)buf, (long)(size > TP_BSIZE ? |
899 | fssize : (curblk - 1) * TP_BSIZE + size)); | | 899 | fssize : (curblk - 1) * TP_BSIZE + size)); |
900 | curblk = 0; | | 900 | curblk = 0; |
901 | } | | 901 | } |
902 | } else { | | 902 | } else { |
903 | if (curblk > 0) { | | 903 | if (curblk > 0) { |
904 | (*fill)((char *)buf, (long)(size > TP_BSIZE ? | | 904 | (*fill)((char *)buf, (long)(size > TP_BSIZE ? |
905 | curblk * TP_BSIZE : | | 905 | curblk * TP_BSIZE : |
906 | (curblk - 1) * TP_BSIZE + size)); | | 906 | (curblk - 1) * TP_BSIZE + size)); |
907 | curblk = 0; | | 907 | curblk = 0; |
908 | } | | 908 | } |
909 | (*skip)(clearedbuf, (long)(size > TP_BSIZE ? | | 909 | (*skip)(clearedbuf, (long)(size > TP_BSIZE ? |
910 | TP_BSIZE : size)); | | 910 | TP_BSIZE : size)); |
911 | } | | 911 | } |
912 | if ((size -= TP_BSIZE) <= 0) { | | 912 | if ((size -= TP_BSIZE) <= 0) { |
913 | for (i++; i < spcl.c_count; i++) | | 913 | for (i++; i < spcl.c_count; i++) |
914 | if (spcl.c_addr[i]) | | 914 | if (spcl.c_addr[i]) |
915 | readtape(junk); | | 915 | readtape(junk); |
916 | break; | | 916 | break; |
917 | } | | 917 | } |
918 | } | | 918 | } |
919 | if (gethead(&spcl) == GOOD && size > 0) { | | 919 | if (gethead(&spcl) == GOOD && size > 0) { |
920 | if (spcl.c_type == TS_ADDR) | | 920 | if (spcl.c_type == TS_ADDR) |
921 | goto loop; | | 921 | goto loop; |
922 | dprintf(stdout, | | 922 | dprintf(stdout, |
923 | "Missing address (header) block for %s at %d blocks\n", | | 923 | "Missing address (header) block for %s at %d blocks\n", |
924 | curfile.name, blksread); | | 924 | curfile.name, blksread); |
925 | } | | 925 | } |
926 | if (curblk > 0) | | 926 | if (curblk > 0) |
927 | (*fill)((char *)buf, (long)((curblk * TP_BSIZE) + size)); | | 927 | (*fill)((char *)buf, (long)((curblk * TP_BSIZE) + size)); |
928 | /* Skip over Linux extended attributes. */ | | 928 | /* Skip over Linux extended attributes. */ |
929 | if (spcl.c_type == TS_INODE && (spcl.c_flags & DR_EXTATTRIBUTES)) { | | 929 | if (spcl.c_type == TS_INODE && (spcl.c_flags & DR_EXTATTRIBUTES)) { |
930 | for (i = 0; i < spcl.c_count; i++) | | 930 | for (i = 0; i < spcl.c_count; i++) |
931 | readtape(junk); | | 931 | readtape(junk); |
932 | (void)gethead(&spcl); | | 932 | (void)gethead(&spcl); |
933 | } | | 933 | } |
934 | findinode(&spcl); | | 934 | findinode(&spcl); |
935 | gettingfile = 0; | | 935 | gettingfile = 0; |
936 | } | | 936 | } |
937 | | | 937 | |
938 | /* | | 938 | /* |
939 | * Write out the next block of a file. | | 939 | * Write out the next block of a file. |
940 | */ | | 940 | */ |
941 | static void | | 941 | static void |
942 | xtrfile(char *buf, long size) | | 942 | xtrfile(char *buf, long size) |
943 | { | | 943 | { |
944 | | | 944 | |
945 | if (Dflag) | | 945 | if (Dflag) |
946 | (*ddesc->dd_update)(&dcontext, buf, size); | | 946 | (*ddesc->dd_update)(&dcontext, buf, size); |
947 | if (Nflag) | | 947 | if (Nflag) |
948 | return; | | 948 | return; |
949 | if (write(ofile, buf, (int) size) == -1) { | | 949 | if (write(ofile, buf, (int) size) == -1) { |
950 | fprintf(stderr, | | 950 | fprintf(stderr, |
951 | "write error extracting inode %llu, name %s\nwrite: %s\n", | | 951 | "write error extracting inode %llu, name %s\nwrite: %s\n", |
952 | (unsigned long long)curfile.ino, curfile.name, | | 952 | (unsigned long long)curfile.ino, curfile.name, |
953 | strerror(errno)); | | 953 | strerror(errno)); |
954 | exit(1); | | 954 | exit(1); |
955 | } | | 955 | } |
956 | } | | 956 | } |
957 | | | 957 | |
958 | /* | | 958 | /* |
959 | * Skip over a hole in a file. | | 959 | * Skip over a hole in a file. |
960 | */ | | 960 | */ |
961 | /* ARGSUSED */ | | 961 | /* ARGSUSED */ |
962 | static void | | 962 | static void |
963 | xtrskip(char *buf, long size) | | 963 | xtrskip(char *buf, long size) |
964 | { | | 964 | { |
965 | | | 965 | |
966 | if (Dflag) | | 966 | if (Dflag) |
967 | (*ddesc->dd_update)(&dcontext, buf, size); | | 967 | (*ddesc->dd_update)(&dcontext, buf, size); |
968 | if (Nflag) | | 968 | if (Nflag) |
969 | return; | | 969 | return; |
970 | if (lseek(ofile, size, SEEK_CUR) == -1) { | | 970 | if (lseek(ofile, size, SEEK_CUR) == -1) { |
971 | fprintf(stderr, | | 971 | fprintf(stderr, |
972 | "seek error extracting inode %llu, name %s\nlseek: %s\n", | | 972 | "seek error extracting inode %llu, name %s\nlseek: %s\n", |
973 | (unsigned long long)curfile.ino, curfile.name, | | 973 | (unsigned long long)curfile.ino, curfile.name, |
974 | strerror(errno)); | | 974 | strerror(errno)); |
975 | exit(1); | | 975 | exit(1); |
976 | } | | 976 | } |
977 | } | | 977 | } |
978 | | | 978 | |
979 | /* | | 979 | /* |
980 | * Collect the next block of a symbolic link. | | 980 | * Collect the next block of a symbolic link. |
981 | */ | | 981 | */ |
982 | static void | | 982 | static void |
983 | xtrlnkfile(char *buf, long size) | | 983 | xtrlnkfile(char *buf, long size) |
984 | { | | 984 | { |
985 | | | 985 | |
986 | pathlen += size; | | 986 | pathlen += size; |
987 | if (pathlen > MAXPATHLEN) { | | 987 | if (pathlen > MAXPATHLEN) { |
988 | fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n", | | 988 | fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n", |
989 | curfile.name, lnkbuf, buf, pathlen); | | 989 | curfile.name, lnkbuf, buf, pathlen); |
990 | exit(1); | | 990 | exit(1); |
991 | } | | 991 | } |
992 | (void) strcat(lnkbuf, buf); | | 992 | (void) strcat(lnkbuf, buf); |
993 | } | | 993 | } |
994 | | | 994 | |
995 | /* | | 995 | /* |
996 | * Skip over a hole in a symbolic link (should never happen). | | 996 | * Skip over a hole in a symbolic link (should never happen). |
997 | */ | | 997 | */ |
998 | /* ARGSUSED */ | | 998 | /* ARGSUSED */ |
999 | static void | | 999 | static void |
1000 | xtrlnkskip(char *buf __unused, long size __unused) | | 1000 | xtrlnkskip(char *buf __unused, long size __unused) |
1001 | { | | 1001 | { |
1002 | | | 1002 | |
1003 | fprintf(stderr, "unallocated block in symbolic link %s\n", | | 1003 | fprintf(stderr, "unallocated block in symbolic link %s\n", |
1004 | curfile.name); | | 1004 | curfile.name); |
1005 | exit(1); | | 1005 | exit(1); |
1006 | } | | 1006 | } |
1007 | | | 1007 | |
1008 | /* | | 1008 | /* |
1009 | * Noop, when an extraction function is not needed. | | 1009 | * Noop, when an extraction function is not needed. |
1010 | */ | | 1010 | */ |
1011 | /* ARGSUSED */ | | 1011 | /* ARGSUSED */ |
1012 | void | | 1012 | void |
1013 | xtrnull(char *buf __unused, long size __unused) | | 1013 | xtrnull(char *buf __unused, long size __unused) |
1014 | { | | 1014 | { |
1015 | | | 1015 | |
1016 | return; | | 1016 | return; |
1017 | } | | 1017 | } |
1018 | | | 1018 | |
1019 | /* | | 1019 | /* |
1020 | * Read TP_BSIZE blocks from the input. | | 1020 | * Read TP_BSIZE blocks from the input. |
1021 | * Handle read errors, and end of media. | | 1021 | * Handle read errors, and end of media. |
1022 | */ | | 1022 | */ |
1023 | static void | | 1023 | static void |
1024 | readtape(char *buf) | | 1024 | readtape(char *buf) |
1025 | { | | 1025 | { |
1026 | int rd, newvol, i; | | 1026 | int rd, newvol, i; |
1027 | int cnt, seek_failed; | | 1027 | int cnt, seek_failed; |
1028 | | | 1028 | |
1029 | if (blkcnt < numtrec) { | | 1029 | if (blkcnt < numtrec) { |
1030 | memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE); | | 1030 | memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE); |
1031 | blksread++; | | 1031 | blksread++; |
1032 | tpblksread++; | | 1032 | tpblksread++; |
1033 | return; | | 1033 | return; |
1034 | } | | 1034 | } |
1035 | for (i = 0; i < ntrec; i++) | | 1035 | for (i = 0; i < ntrec; i++) |
1036 | ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; | | 1036 | ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; |
1037 | if (numtrec == 0) | | 1037 | if (numtrec == 0) |
1038 | numtrec = ntrec; | | 1038 | numtrec = ntrec; |
1039 | cnt = ntrec * TP_BSIZE; | | 1039 | cnt = ntrec * TP_BSIZE; |
1040 | rd = 0; | | 1040 | rd = 0; |
1041 | getmore: | | 1041 | getmore: |
1042 | #ifdef RRESTORE | | 1042 | #ifdef RRESTORE |
1043 | if (host) | | 1043 | if (host) |
1044 | i = rmtread(&tapebuf[rd], cnt); | | 1044 | i = rmtread(&tapebuf[rd], cnt); |
1045 | else | | 1045 | else |
1046 | #endif | | 1046 | #endif |
1047 | i = read(mt, &tapebuf[rd], cnt); | | 1047 | i = read(mt, &tapebuf[rd], cnt); |
1048 | /* | | 1048 | /* |
1049 | * Check for mid-tape short read error. | | 1049 | * Check for mid-tape short read error. |
1050 | * If found, skip rest of buffer and start with the next. | | 1050 | * If found, skip rest of buffer and start with the next. |
1051 | */ | | 1051 | */ |
1052 | if (!pipein && numtrec < ntrec && i > 0) { | | 1052 | if (!pipein && numtrec < ntrec && i > 0) { |
1053 | dprintf(stdout, "mid-media short read error.\n"); | | 1053 | dprintf(stdout, "mid-media short read error.\n"); |
1054 | numtrec = ntrec; | | 1054 | numtrec = ntrec; |
1055 | } | | 1055 | } |
1056 | /* | | 1056 | /* |
1057 | * Handle partial block read. | | 1057 | * Handle partial block read. |
1058 | */ | | 1058 | */ |
1059 | if (pipein && i == 0 && rd > 0) | | 1059 | if (pipein && i == 0 && rd > 0) |
1060 | i = rd; | | 1060 | i = rd; |
1061 | else if (i > 0 && i != ntrec * TP_BSIZE) { | | 1061 | else if (i > 0 && i != ntrec * TP_BSIZE) { |
1062 | if (pipein) { | | 1062 | if (pipein) { |
1063 | rd += i; | | 1063 | rd += i; |
1064 | cnt -= i; | | 1064 | cnt -= i; |
1065 | if (cnt > 0) | | 1065 | if (cnt > 0) |
1066 | goto getmore; | | 1066 | goto getmore; |
1067 | i = rd; | | 1067 | i = rd; |
1068 | } else { | | 1068 | } else { |
1069 | /* | | 1069 | /* |
1070 | * Short read. Process the blocks read. | | 1070 | * Short read. Process the blocks read. |
1071 | */ | | 1071 | */ |
1072 | if (i % TP_BSIZE != 0) | | 1072 | if (i % TP_BSIZE != 0) |
1073 | vprintf(stdout, | | 1073 | vprintf(stdout, |
1074 | "partial block read: %d should be %d\n", | | 1074 | "partial block read: %d should be %d\n", |
1075 | i, ntrec * TP_BSIZE); | | 1075 | i, ntrec * TP_BSIZE); |
1076 | numtrec = i / TP_BSIZE; | | 1076 | numtrec = i / TP_BSIZE; |
1077 | } | | 1077 | } |
1078 | } | | 1078 | } |
1079 | /* | | 1079 | /* |
1080 | * Handle read error. | | 1080 | * Handle read error. |
1081 | */ | | 1081 | */ |
1082 | if (i < 0) { | | 1082 | if (i < 0) { |
1083 | fprintf(stderr, "Tape read error while "); | | 1083 | fprintf(stderr, "Tape read error while "); |
1084 | switch (curfile.action) { | | 1084 | switch (curfile.action) { |
1085 | default: | | 1085 | default: |
1086 | fprintf(stderr, "trying to set up tape\n"); | | 1086 | fprintf(stderr, "trying to set up tape\n"); |
1087 | break; | | 1087 | break; |
1088 | case UNKNOWN: | | 1088 | case UNKNOWN: |
1089 | fprintf(stderr, "trying to resynchronize\n"); | | 1089 | fprintf(stderr, "trying to resynchronize\n"); |
1090 | break; | | 1090 | break; |
1091 | case USING: | | 1091 | case USING: |
1092 | fprintf(stderr, "restoring %s\n", curfile.name); | | 1092 | fprintf(stderr, "restoring %s\n", curfile.name); |
1093 | break; | | 1093 | break; |
1094 | case SKIP: | | 1094 | case SKIP: |
1095 | fprintf(stderr, "skipping over inode %llu\n", | | 1095 | fprintf(stderr, "skipping over inode %llu\n", |
1096 | (unsigned long long)curfile.ino); | | 1096 | (unsigned long long)curfile.ino); |
1097 | break; | | 1097 | break; |
1098 | } | | 1098 | } |
1099 | if (!yflag && !reply("continue")) | | 1099 | if (!yflag && !reply("continue")) |
1100 | exit(1); | | 1100 | exit(1); |
1101 | i = ntrec * TP_BSIZE; | | 1101 | i = ntrec * TP_BSIZE; |
1102 | memset(tapebuf, 0, i); | | 1102 | memset(tapebuf, 0, i); |
1103 | #ifdef RRESTORE | | 1103 | #ifdef RRESTORE |
1104 | if (host) | | 1104 | if (host) |
1105 | seek_failed = (rmtseek(i, 1) < 0); | | 1105 | seek_failed = (rmtseek(i, 1) < 0); |
1106 | else | | 1106 | else |
1107 | #endif | | 1107 | #endif |
1108 | seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1); | | 1108 | seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1); |
1109 | | | 1109 | |
1110 | if (seek_failed) { | | 1110 | if (seek_failed) { |
1111 | fprintf(stderr, | | 1111 | fprintf(stderr, |
1112 | "continuation failed: %s\n", strerror(errno)); | | 1112 | "continuation failed: %s\n", strerror(errno)); |
1113 | exit(1); | | 1113 | exit(1); |
1114 | } | | 1114 | } |
1115 | } | | 1115 | } |
1116 | /* | | 1116 | /* |
1117 | * Handle end of tape. | | 1117 | * Handle end of tape. |
1118 | */ | | 1118 | */ |
1119 | if (i == 0) { | | 1119 | if (i == 0) { |
1120 | vprintf(stdout, "End-of-tape encountered\n"); | | 1120 | vprintf(stdout, "End-of-tape encountered\n"); |
1121 | if (!pipein) { | | 1121 | if (!pipein) { |
1122 | newvol = volno + 1; | | 1122 | newvol = volno + 1; |
1123 | volno = 0; | | 1123 | volno = 0; |
1124 | numtrec = 0; | | 1124 | numtrec = 0; |
1125 | getvol(newvol); | | 1125 | getvol(newvol); |
1126 | readtape(buf); | | 1126 | readtape(buf); |
1127 | return; | | 1127 | return; |
1128 | } | | 1128 | } |
1129 | if (rd % TP_BSIZE != 0) | | 1129 | if (rd % TP_BSIZE != 0) |
1130 | panic("partial block read: %d should be %d\n", | | 1130 | panic("partial block read: %d should be %d\n", |
1131 | rd, ntrec * TP_BSIZE); | | 1131 | rd, ntrec * TP_BSIZE); |
1132 | terminateinput(); | | 1132 | terminateinput(); |
1133 | memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE); | | 1133 | memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE); |
1134 | } | | 1134 | } |
1135 | blkcnt = 0; | | 1135 | blkcnt = 0; |
1136 | memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE); | | 1136 | memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE); |
1137 | blksread++; | | 1137 | blksread++; |
1138 | tpblksread++; | | 1138 | tpblksread++; |
1139 | } | | 1139 | } |
1140 | | | 1140 | |
1141 | static void | | 1141 | static void |
1142 | findtapeblksize(void) | | 1142 | findtapeblksize(void) |
1143 | { | | 1143 | { |
1144 | long i; | | 1144 | long i; |
1145 | | | 1145 | |
1146 | for (i = 0; i < ntrec; i++) | | 1146 | for (i = 0; i < ntrec; i++) |
1147 | ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; | | 1147 | ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; |
1148 | blkcnt = 0; | | 1148 | blkcnt = 0; |
1149 | #ifdef RRESTORE | | 1149 | #ifdef RRESTORE |
1150 | if (host) | | 1150 | if (host) |
1151 | i = rmtread(tapebuf, ntrec * TP_BSIZE); | | 1151 | i = rmtread(tapebuf, ntrec * TP_BSIZE); |
1152 | else | | 1152 | else |
1153 | #endif | | 1153 | #endif |
1154 | i = read(mt, tapebuf, ntrec * TP_BSIZE); | | 1154 | i = read(mt, tapebuf, ntrec * TP_BSIZE); |
1155 | | | 1155 | |
1156 | if (i <= 0) { | | 1156 | if (i <= 0) { |
1157 | fprintf(stderr, "tape read error: %s\n", strerror(errno)); | | 1157 | fprintf(stderr, "tape read error: %s\n", strerror(errno)); |
1158 | exit(1); | | 1158 | exit(1); |
1159 | } | | 1159 | } |
1160 | if (i % TP_BSIZE != 0) { | | 1160 | if (i % TP_BSIZE != 0) { |
1161 | fprintf(stderr, "Tape block size (%ld) %s (%ld)\n", | | 1161 | fprintf(stderr, "Tape block size (%ld) %s (%ld)\n", |
1162 | (long)i, "is not a multiple of dump block size", | | 1162 | (long)i, "is not a multiple of dump block size", |
1163 | (long)TP_BSIZE); | | 1163 | (long)TP_BSIZE); |
1164 | exit(1); | | 1164 | exit(1); |
1165 | } | | 1165 | } |
1166 | ntrec = i / TP_BSIZE; | | 1166 | ntrec = i / TP_BSIZE; |
1167 | numtrec = ntrec; | | 1167 | numtrec = ntrec; |
1168 | vprintf(stdout, "Tape block size is %d\n", ntrec); | | 1168 | vprintf(stdout, "Tape block size is %d\n", ntrec); |
1169 | } | | 1169 | } |
1170 | | | 1170 | |
1171 | void | | 1171 | void |
1172 | closemt(void) | | 1172 | closemt(void) |
1173 | { | | 1173 | { |
1174 | | | 1174 | |
1175 | if (mt < 0) | | 1175 | if (mt < 0) |
1176 | return; | | 1176 | return; |
1177 | #ifdef RRESTORE | | 1177 | #ifdef RRESTORE |
1178 | if (host) | | 1178 | if (host) |
1179 | rmtclose(); | | 1179 | rmtclose(); |
1180 | else | | 1180 | else |
1181 | #endif | | 1181 | #endif |
1182 | (void) close(mt); | | 1182 | (void) close(mt); |
1183 | } | | 1183 | } |
1184 | | | 1184 | |
1185 | /* | | 1185 | /* |
1186 | * Read the next block from the tape. | | 1186 | * Read the next block from the tape. |
1187 | * Check to see if it is one of several vintage headers. | | 1187 | * Check to see if it is one of several vintage headers. |
1188 | * If it is an old style header, convert it to a new style header. | | 1188 | * If it is an old style header, convert it to a new style header. |
1189 | * If it is not any valid header, return an error. | | 1189 | * If it is not any valid header, return an error. |
1190 | */ | | 1190 | */ |
1191 | static int | | 1191 | static int |
1192 | gethead(struct s_spcl *buf) | | 1192 | gethead(struct s_spcl *buf) |
1193 | { | | 1193 | { |
1194 | union u_ospcl u_ospcl; | | 1194 | union u_ospcl u_ospcl; |
1195 | | | 1195 | |
1196 | if (!cvtflag) { | | 1196 | if (!cvtflag) { |
1197 | readtape((char *)buf); | | 1197 | readtape((char *)buf); |
1198 | if (buf->c_magic != NFS_MAGIC && | | 1198 | if (buf->c_magic != NFS_MAGIC && |
1199 | buf->c_magic != FS_UFS2_MAGIC) { | | 1199 | buf->c_magic != FS_UFS2_MAGIC) { |
1200 | if (bswap32(buf->c_magic) != NFS_MAGIC && | | 1200 | if (bswap32(buf->c_magic) != NFS_MAGIC && |
1201 | bswap32(buf->c_magic) != FS_UFS2_MAGIC) | | 1201 | bswap32(buf->c_magic) != FS_UFS2_MAGIC) |
1202 | return (FAIL); | | 1202 | return (FAIL); |
1203 | if (!Bcvt) { | | 1203 | if (!Bcvt) { |
1204 | vprintf(stdout, "Note: Doing Byte swapping\n"); | | 1204 | vprintf(stdout, "Note: Doing Byte swapping\n"); |
1205 | Bcvt = 1; | | 1205 | Bcvt = 1; |
1206 | } | | 1206 | } |
1207 | } | | 1207 | } |
1208 | if (checksum((int *)buf) == FAIL) | | 1208 | if (checksum((int *)buf) == FAIL) |
1209 | return (FAIL); | | 1209 | return (FAIL); |
1210 | if (Bcvt) | | 1210 | if (Bcvt) |
1211 | swap_header(buf); | | 1211 | swap_header(buf); |
1212 | goto good; | | 1212 | goto good; |
1213 | } | | 1213 | } |
1214 | | | 1214 | |
1215 | readtape((char *)(&u_ospcl.s_ospcl)); | | 1215 | readtape((char *)(&u_ospcl.s_ospcl)); |
1216 | if (checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) | | 1216 | if (checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) |
1217 | return (FAIL); | | 1217 | return (FAIL); |
1218 | if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC) { | | 1218 | if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC) { |
1219 | if (bswap32(u_ospcl.s_ospcl.c_magic) != OFS_MAGIC) | | 1219 | if (bswap32(u_ospcl.s_ospcl.c_magic) != OFS_MAGIC) |
1220 | return (FAIL); | | 1220 | return (FAIL); |
1221 | if (!Bcvt) { | | 1221 | if (!Bcvt) { |
1222 | vprintf(stdout, "Note: Doing Byte swapping\n"); | | 1222 | vprintf(stdout, "Note: Doing Byte swapping\n"); |
1223 | Bcvt = 1; | | 1223 | Bcvt = 1; |
1224 | } | | 1224 | } |
1225 | swap_old_header(&u_ospcl.s_ospcl); | | 1225 | swap_old_header(&u_ospcl.s_ospcl); |
1226 | } | | 1226 | } |
1227 | | | 1227 | |
1228 | memset(buf, 0, TP_BSIZE); | | 1228 | memset(buf, 0, TP_BSIZE); |
1229 | buf->c_type = u_ospcl.s_ospcl.c_type; | | 1229 | buf->c_type = u_ospcl.s_ospcl.c_type; |
1230 | buf->c_date = u_ospcl.s_ospcl.c_date; | | 1230 | buf->c_date = u_ospcl.s_ospcl.c_date; |
1231 | buf->c_ddate = u_ospcl.s_ospcl.c_ddate; | | 1231 | buf->c_ddate = u_ospcl.s_ospcl.c_ddate; |
1232 | buf->c_volume = u_ospcl.s_ospcl.c_volume; | | 1232 | buf->c_volume = u_ospcl.s_ospcl.c_volume; |
1233 | buf->c_tapea = u_ospcl.s_ospcl.c_tapea; | | 1233 | buf->c_tapea = u_ospcl.s_ospcl.c_tapea; |
1234 | buf->c_inumber = u_ospcl.s_ospcl.c_inumber; | | 1234 | buf->c_inumber = u_ospcl.s_ospcl.c_inumber; |
1235 | buf->c_checksum = u_ospcl.s_ospcl.c_checksum; | | 1235 | buf->c_checksum = u_ospcl.s_ospcl.c_checksum; |
1236 | buf->c_mode = u_ospcl.s_ospcl.c_odinode.odi_mode; | | 1236 | buf->c_mode = u_ospcl.s_ospcl.c_odinode.odi_mode; |
1237 | buf->c_uid = u_ospcl.s_ospcl.c_odinode.odi_uid; | | 1237 | buf->c_uid = u_ospcl.s_ospcl.c_odinode.odi_uid; |
1238 | buf->c_gid = u_ospcl.s_ospcl.c_odinode.odi_gid; | | 1238 | buf->c_gid = u_ospcl.s_ospcl.c_odinode.odi_gid; |
1239 | buf->c_size = u_ospcl.s_ospcl.c_odinode.odi_size; | | 1239 | buf->c_size = u_ospcl.s_ospcl.c_odinode.odi_size; |
1240 | buf->c_rdev = u_ospcl.s_ospcl.c_odinode.odi_rdev; | | 1240 | buf->c_rdev = u_ospcl.s_ospcl.c_odinode.odi_rdev; |
1241 | buf->c_atime = u_ospcl.s_ospcl.c_odinode.odi_atime; | | 1241 | buf->c_atime = u_ospcl.s_ospcl.c_odinode.odi_atime; |
1242 | buf->c_mtime = u_ospcl.s_ospcl.c_odinode.odi_mtime; | | 1242 | buf->c_mtime = u_ospcl.s_ospcl.c_odinode.odi_mtime; |
1243 | buf->c_count = u_ospcl.s_ospcl.c_count; | | 1243 | buf->c_count = u_ospcl.s_ospcl.c_count; |
1244 | memmove(buf->c_addr, u_ospcl.s_ospcl.c_addr, (long)256); | | 1244 | memmove(buf->c_addr, u_ospcl.s_ospcl.c_addr, (long)256); |
1245 | buf->c_magic = FS_UFS2_MAGIC; | | 1245 | buf->c_magic = FS_UFS2_MAGIC; |
1246 | good: | | 1246 | good: |
1247 | switch (buf->c_type) { | | 1247 | switch (buf->c_type) { |
1248 | | | 1248 | |
1249 | case TS_CLRI: | | 1249 | case TS_CLRI: |
1250 | case TS_BITS: | | 1250 | case TS_BITS: |
1251 | /* | | 1251 | /* |
1252 | * Have to patch up missing information in bit map headers | | 1252 | * Have to patch up missing information in bit map headers |
1253 | */ | | 1253 | */ |
1254 | buf->c_inumber = 0; | | 1254 | buf->c_inumber = 0; |
1255 | buf->c_size = buf->c_count * TP_BSIZE; | | 1255 | buf->c_size = buf->c_count * TP_BSIZE; |
1256 | break; | | 1256 | break; |
1257 | | | 1257 | |
1258 | case TS_TAPE: | | 1258 | case TS_TAPE: |
1259 | if ((buf->c_flags & DR_NEWINODEFMT) == 0) | | 1259 | if ((buf->c_flags & DR_NEWINODEFMT) == 0) |
1260 | oldinofmt = 1; | | 1260 | oldinofmt = 1; |
1261 | /* fall through */ | | 1261 | /* fall through */ |
1262 | case TS_END: | | 1262 | case TS_END: |
1263 | buf->c_inumber = 0; | | 1263 | buf->c_inumber = 0; |
1264 | break; | | 1264 | break; |
1265 | | | 1265 | |
1266 | case TS_INODE: | | 1266 | case TS_INODE: |
1267 | if (buf->c_magic == NFS_MAGIC) { | | 1267 | if (buf->c_magic == NFS_MAGIC) { |
1268 | buf->c_tapea = buf->c_old_tapea; | | 1268 | buf->c_tapea = buf->c_old_tapea; |
1269 | buf->c_firstrec = buf->c_old_firstrec; | | 1269 | buf->c_firstrec = buf->c_old_firstrec; |
1270 | buf->c_date = buf->c_old_date; | | 1270 | buf->c_date = buf->c_old_date; |
1271 | buf->c_ddate = buf->c_old_ddate; | | 1271 | buf->c_ddate = buf->c_old_ddate; |
1272 | buf->c_atime = buf->c_old_atime; | | 1272 | buf->c_atime = buf->c_old_atime; |
1273 | buf->c_mtime = buf->c_old_mtime; | | 1273 | buf->c_mtime = buf->c_old_mtime; |
1274 | buf->c_birthtime = 0; | | 1274 | buf->c_birthtime = 0; |
1275 | buf->c_birthtimensec = 0; | | 1275 | buf->c_birthtimensec = 0; |
1276 | buf->c_atimensec = buf->c_mtimensec = 0; | | 1276 | buf->c_atimensec = buf->c_mtimensec = 0; |
1277 | } | | 1277 | } |
1278 | | | 1278 | |
1279 | case TS_ADDR: | | 1279 | case TS_ADDR: |
1280 | break; | | 1280 | break; |
1281 | | | 1281 | |
1282 | default: | | 1282 | default: |
1283 | panic("gethead: unknown inode type %d\n", buf->c_type); | | 1283 | panic("gethead: unknown inode type %d\n", buf->c_type); |
1284 | break; | | 1284 | break; |
1285 | } | | 1285 | } |
1286 | | | 1286 | |
1287 | buf->c_magic = FS_UFS2_MAGIC; | | 1287 | buf->c_magic = FS_UFS2_MAGIC; |
1288 | | | 1288 | |
1289 | /* | | 1289 | /* |
1290 | * If we are restoring a filesystem with old format inodes, | | 1290 | * If we are restoring a filesystem with old format inodes, |
1291 | * copy the uid/gid to the new location. | | 1291 | * copy the uid/gid to the new location. |
1292 | */ | | 1292 | */ |
1293 | if (oldinofmt) { | | 1293 | if (oldinofmt) { |
1294 | buf->c_uid = buf->c_spare1[1]; | | 1294 | buf->c_uid = buf->c_spare1[1]; |
1295 | buf->c_gid = buf->c_spare1[2]; | | 1295 | buf->c_gid = buf->c_spare1[2]; |
1296 | } | | 1296 | } |
1297 | if (dflag) | | 1297 | if (dflag) |
1298 | accthdr(buf); | | 1298 | accthdr(buf); |
1299 | return(GOOD); | | 1299 | return(GOOD); |
1300 | } | | 1300 | } |
1301 | | | 1301 | |
1302 | /* | | 1302 | /* |
1303 | * Check that a header is where it belongs and predict the next header | | 1303 | * Check that a header is where it belongs and predict the next header |
1304 | */ | | 1304 | */ |
1305 | static void | | 1305 | static void |
1306 | accthdr(struct s_spcl *header) | | 1306 | accthdr(struct s_spcl *header) |
1307 | { | | 1307 | { |
1308 | static ino_t previno = 0x7fffffff; | | 1308 | static ino_t previno = 0x7fffffff; |
1309 | static int prevtype; | | 1309 | static int prevtype; |
1310 | static long predict; | | 1310 | static long predict; |
1311 | long blks, i; | | 1311 | long blks, i; |
1312 | | | 1312 | |
1313 | if (header->c_type == TS_TAPE) { | | 1313 | if (header->c_type == TS_TAPE) { |
1314 | fprintf(stderr, "Volume header (%s inode format) ", | | 1314 | fprintf(stderr, "Volume header (%s inode format) ", |
1315 | oldinofmt ? "old" : "new"); | | 1315 | oldinofmt ? "old" : "new"); |
1316 | if (header->c_firstrec) | | 1316 | if (header->c_firstrec) |
1317 | fprintf(stderr, "begins with record %lld", | | 1317 | fprintf(stderr, "begins with record %lld", |
1318 | (long long)header->c_firstrec); | | 1318 | (long long)header->c_firstrec); |
1319 | fprintf(stderr, "\n"); | | 1319 | fprintf(stderr, "\n"); |
1320 | previno = 0x7fffffff; | | 1320 | previno = 0x7fffffff; |
1321 | return; | | 1321 | return; |
1322 | } | | 1322 | } |
1323 | if (previno == 0x7fffffff) | | 1323 | if (previno == 0x7fffffff) |
1324 | goto newcalc; | | 1324 | goto newcalc; |
1325 | switch (prevtype) { | | 1325 | switch (prevtype) { |
1326 | case TS_BITS: | | 1326 | case TS_BITS: |
1327 | fprintf(stderr, "Dumped inodes map header"); | | 1327 | fprintf(stderr, "Dumped inodes map header"); |
1328 | break; | | 1328 | break; |
1329 | case TS_CLRI: | | 1329 | case TS_CLRI: |
1330 | fprintf(stderr, "Used inodes map header"); | | 1330 | fprintf(stderr, "Used inodes map header"); |
1331 | break; | | 1331 | break; |
1332 | case TS_INODE: | | 1332 | case TS_INODE: |
1333 | fprintf(stderr, "File header, ino %llu", | | 1333 | fprintf(stderr, "File header, ino %llu", |
1334 | (unsigned long long)previno); | | 1334 | (unsigned long long)previno); |
1335 | break; | | 1335 | break; |
1336 | case TS_ADDR: | | 1336 | case TS_ADDR: |
1337 | fprintf(stderr, "File continuation header, ino %llu", | | 1337 | fprintf(stderr, "File continuation header, ino %llu", |
1338 | (unsigned long long)previno); | | 1338 | (unsigned long long)previno); |
1339 | break; | | 1339 | break; |
1340 | case TS_END: | | 1340 | case TS_END: |
1341 | fprintf(stderr, "End of tape header"); | | 1341 | fprintf(stderr, "End of tape header"); |
1342 | break; | | 1342 | break; |
1343 | } | | 1343 | } |
1344 | if (predict != blksread - 1) | | 1344 | if (predict != blksread - 1) |
1345 | fprintf(stderr, "; predicted %ld blocks, got %ld blocks", | | 1345 | fprintf(stderr, "; predicted %ld blocks, got %ld blocks", |
1346 | (long)predict, (long)(blksread - 1)); | | 1346 | (long)predict, (long)(blksread - 1)); |
1347 | fprintf(stderr, "\n"); | | 1347 | fprintf(stderr, "\n"); |
1348 | newcalc: | | 1348 | newcalc: |
1349 | blks = 0; | | 1349 | blks = 0; |
1350 | switch (header->c_type) { | | 1350 | switch (header->c_type) { |
1351 | case TS_END: | | 1351 | case TS_END: |
1352 | break; | | 1352 | break; |
1353 | case TS_CLRI: | | 1353 | case TS_CLRI: |
1354 | case TS_BITS: | | 1354 | case TS_BITS: |
1355 | blks = header->c_count; | | 1355 | blks = header->c_count; |
1356 | break; | | 1356 | break; |
1357 | default: | | 1357 | default: |
1358 | for (i = 0; i < header->c_count; i++) | | 1358 | for (i = 0; i < header->c_count; i++) |
1359 | if (header->c_addr[i] != 0) | | 1359 | if (header->c_addr[i] != 0) |
1360 | blks++; | | 1360 | blks++; |
1361 | break; | | 1361 | break; |
1362 | } | | 1362 | } |
1363 | predict = blks; | | 1363 | predict = blks; |
1364 | blksread = 0; | | 1364 | blksread = 0; |
1365 | prevtype = header->c_type; | | 1365 | prevtype = header->c_type; |
1366 | previno = header->c_inumber; | | 1366 | previno = header->c_inumber; |
1367 | } | | 1367 | } |
1368 | | | 1368 | |
1369 | /* | | 1369 | /* |
1370 | * Find an inode header. | | 1370 | * Find an inode header. |
1371 | * Complain if had to skip, and complain is set. | | 1371 | * Complain if had to skip, and complain is set. |
1372 | */ | | 1372 | */ |
1373 | static void | | 1373 | static void |
1374 | findinode(struct s_spcl *header) | | 1374 | findinode(struct s_spcl *header) |
1375 | { | | 1375 | { |
1376 | static long skipcnt = 0; | | 1376 | static long skipcnt = 0; |
1377 | long i; | | 1377 | long i; |
1378 | char buf[TP_BSIZE]; | | 1378 | char buf[TP_BSIZE]; |
1379 | | | 1379 | |
1380 | curfile.name = "<name unknown>"; | | 1380 | curfile.name = "<name unknown>"; |
1381 | curfile.action = UNKNOWN; | | 1381 | curfile.action = UNKNOWN; |
1382 | curfile.mode = 0; | | 1382 | curfile.mode = 0; |
1383 | curfile.ino = 0; | | 1383 | curfile.ino = 0; |
1384 | top: | | 1384 | top: |
1385 | do { | | 1385 | do { |
1386 | if (header->c_magic != FS_UFS2_MAGIC) { | | 1386 | if (header->c_magic != FS_UFS2_MAGIC) { |
1387 | skip: | | 1387 | skip: |
1388 | skipcnt++; | | 1388 | skipcnt++; |
1389 | while (gethead(header) == FAIL || | | 1389 | while (gethead(header) == FAIL || |
1390 | header->c_date != dumpdate) | | 1390 | header->c_date != dumpdate) |
1391 | skipcnt++; | | 1391 | skipcnt++; |
1392 | } | | 1392 | } |
1393 | switch (header->c_type) { | | 1393 | switch (header->c_type) { |
1394 | | | 1394 | |
1395 | case TS_ADDR: | | 1395 | case TS_ADDR: |
1396 | /* | | 1396 | /* |
1397 | * Skip up to the beginning of the next record | | 1397 | * Skip up to the beginning of the next record |
1398 | */ | | 1398 | */ |
1399 | for (i = 0; i < header->c_count; i++) | | 1399 | for (i = 0; i < header->c_count; i++) |
1400 | if (header->c_addr[i]) | | 1400 | if (header->c_addr[i]) |
1401 | readtape(buf); | | 1401 | readtape(buf); |
1402 | while (gethead(header) == FAIL || | | 1402 | while (gethead(header) == FAIL || |
1403 | header->c_date != dumpdate) | | 1403 | header->c_date != dumpdate) |
1404 | skipcnt++; | | 1404 | skipcnt++; |
1405 | /* We've read a header; don't drop it. */ | | 1405 | /* We've read a header; don't drop it. */ |
1406 | goto top; | | 1406 | goto top; |
1407 | | | 1407 | |
1408 | case TS_INODE: | | 1408 | case TS_INODE: |
1409 | curfile.mode = header->c_mode; | | 1409 | curfile.mode = header->c_mode; |
1410 | curfile.uid = header->c_uid; | | 1410 | curfile.uid = header->c_uid; |
1411 | curfile.gid = header->c_gid; | | 1411 | curfile.gid = header->c_gid; |
1412 | curfile.file_flags = header->c_file_flags; | | 1412 | curfile.file_flags = header->c_file_flags; |
1413 | curfile.rdev = header->c_rdev; | | 1413 | curfile.rdev = header->c_rdev; |
1414 | curfile.atime_sec = header->c_atime; | | 1414 | curfile.atime_sec = header->c_atime; |
1415 | curfile.atime_nsec = header->c_atimensec; | | 1415 | curfile.atime_nsec = header->c_atimensec; |
1416 | curfile.mtime_sec = header->c_mtime; | | 1416 | curfile.mtime_sec = header->c_mtime; |
1417 | curfile.mtime_nsec = header->c_mtimensec; | | 1417 | curfile.mtime_nsec = header->c_mtimensec; |
1418 | curfile.birthtime_sec = header->c_birthtime; | | 1418 | curfile.birthtime_sec = header->c_birthtime; |
1419 | curfile.birthtime_nsec = header->c_birthtimensec; | | 1419 | curfile.birthtime_nsec = header->c_birthtimensec; |
1420 | curfile.size = header->c_size; | | 1420 | curfile.size = header->c_size; |
1421 | curfile.ino = header->c_inumber; | | 1421 | curfile.ino = header->c_inumber; |
1422 | break; | | 1422 | break; |
1423 | | | 1423 | |
1424 | case TS_END: | | 1424 | case TS_END: |
1425 | curfile.ino = maxino; | | 1425 | curfile.ino = maxino; |
1426 | break; | | 1426 | break; |
1427 | | | 1427 | |
1428 | case TS_CLRI: | | 1428 | case TS_CLRI: |
1429 | curfile.name = "<file removal list>"; | | 1429 | curfile.name = "<file removal list>"; |
1430 | break; | | 1430 | break; |
1431 | | | 1431 | |
1432 | case TS_BITS: | | 1432 | case TS_BITS: |
1433 | curfile.name = "<file dump list>"; | | 1433 | curfile.name = "<file dump list>"; |
1434 | break; | | 1434 | break; |
1435 | | | 1435 | |
1436 | case TS_TAPE: | | 1436 | case TS_TAPE: |
1437 | panic("unexpected tape header\n"); | | 1437 | panic("unexpected tape header\n"); |
1438 | break; | | 1438 | break; |
1439 | | | 1439 | |
1440 | default: | | 1440 | default: |
1441 | panic("unknown tape header type %d\n", spcl.c_type); | | 1441 | panic("unknown tape header type %d\n", spcl.c_type); |
1442 | fprintf(stderr, "skiping to next header\n"); | | 1442 | fprintf(stderr, "skipping to next header\n"); |
1443 | goto skip; | | 1443 | goto skip; |
1444 | | | 1444 | |
1445 | } | | 1445 | } |
1446 | } while (header->c_type == TS_ADDR); | | 1446 | } while (header->c_type == TS_ADDR); |
1447 | if (skipcnt > 0) | | 1447 | if (skipcnt > 0) |
1448 | fprintf(stderr, "resync restore, skipped %ld blocks\n", | | 1448 | fprintf(stderr, "resync restore, skipped %ld blocks\n", |
1449 | (long)skipcnt); | | 1449 | (long)skipcnt); |
1450 | skipcnt = 0; | | 1450 | skipcnt = 0; |
1451 | } | | 1451 | } |
1452 | | | 1452 | |
1453 | static int | | 1453 | static int |
1454 | checksum(int *buf) | | 1454 | checksum(int *buf) |
1455 | { | | 1455 | { |
1456 | int i, j; | | 1456 | int i, j; |
1457 | | | 1457 | |
1458 | j = sizeof(union u_spcl) / sizeof(int); | | 1458 | j = sizeof(union u_spcl) / sizeof(int); |
1459 | i = 0; | | 1459 | i = 0; |
1460 | if(!Bcvt) { | | 1460 | if(!Bcvt) { |
1461 | do | | 1461 | do |
1462 | i += *buf++; | | 1462 | i += *buf++; |
1463 | while (--j); | | 1463 | while (--j); |
1464 | } else { | | 1464 | } else { |
1465 | do | | 1465 | do |
1466 | i += bswap32(*buf++); | | 1466 | i += bswap32(*buf++); |
1467 | while (--j); | | 1467 | while (--j); |
1468 | } | | 1468 | } |
1469 | | | 1469 | |
1470 | if (i != CHECKSUM) { | | 1470 | if (i != CHECKSUM) { |
1471 | fprintf(stderr, "Checksum error %o, inode %llu file %s\n", i, | | 1471 | fprintf(stderr, "Checksum error %o, inode %llu file %s\n", i, |
1472 | (unsigned long long)curfile.ino, curfile.name); | | 1472 | (unsigned long long)curfile.ino, curfile.name); |
1473 | return(FAIL); | | 1473 | return(FAIL); |
1474 | } | | 1474 | } |
1475 | return(GOOD); | | 1475 | return(GOOD); |
1476 | } | | 1476 | } |
1477 | | | 1477 | |
1478 | #ifdef RRESTORE | | 1478 | #ifdef RRESTORE |
1479 | #include <stdarg.h> | | 1479 | #include <stdarg.h> |
1480 | | | 1480 | |
1481 | void | | 1481 | void |
1482 | msg(const char *fmt, ...) | | 1482 | msg(const char *fmt, ...) |
1483 | { | | 1483 | { |
1484 | va_list ap; | | 1484 | va_list ap; |
1485 | | | 1485 | |
1486 | va_start(ap, fmt); | | 1486 | va_start(ap, fmt); |
1487 | (void)vfprintf(stderr, fmt, ap); | | 1487 | (void)vfprintf(stderr, fmt, ap); |
1488 | va_end(ap); | | 1488 | va_end(ap); |
1489 | } | | 1489 | } |
1490 | #endif /* RRESTORE */ | | 1490 | #endif /* RRESTORE */ |
1491 | | | 1491 | |
1492 | static void | | 1492 | static void |
1493 | swap_header(struct s_spcl *s) | | 1493 | swap_header(struct s_spcl *s) |
1494 | { | | 1494 | { |
1495 | s->c_type = bswap32(s->c_type); | | 1495 | s->c_type = bswap32(s->c_type); |
1496 | s->c_old_date = bswap32(s->c_old_date); | | 1496 | s->c_old_date = bswap32(s->c_old_date); |
1497 | s->c_old_ddate = bswap32(s->c_old_ddate); | | 1497 | s->c_old_ddate = bswap32(s->c_old_ddate); |
1498 | s->c_volume = bswap32(s->c_volume); | | 1498 | s->c_volume = bswap32(s->c_volume); |
1499 | s->c_old_tapea = bswap32(s->c_old_tapea); | | 1499 | s->c_old_tapea = bswap32(s->c_old_tapea); |
1500 | s->c_inumber = bswap32(s->c_inumber); | | 1500 | s->c_inumber = bswap32(s->c_inumber); |
1501 | s->c_magic = bswap32(s->c_magic); | | 1501 | s->c_magic = bswap32(s->c_magic); |
1502 | s->c_checksum = bswap32(s->c_checksum); | | 1502 | s->c_checksum = bswap32(s->c_checksum); |
1503 | | | 1503 | |
1504 | s->c_mode = bswap16(s->c_mode); | | 1504 | s->c_mode = bswap16(s->c_mode); |
1505 | s->c_size = bswap64(s->c_size); | | 1505 | s->c_size = bswap64(s->c_size); |
1506 | s->c_old_atime = bswap32(s->c_old_atime); | | 1506 | s->c_old_atime = bswap32(s->c_old_atime); |
1507 | s->c_atimensec = bswap32(s->c_atimensec); | | 1507 | s->c_atimensec = bswap32(s->c_atimensec); |
1508 | s->c_old_mtime = bswap32(s->c_old_mtime); | | 1508 | s->c_old_mtime = bswap32(s->c_old_mtime); |
1509 | s->c_mtimensec = bswap32(s->c_mtimensec); | | 1509 | s->c_mtimensec = bswap32(s->c_mtimensec); |
1510 | s->c_rdev = bswap32(s->c_rdev); | | 1510 | s->c_rdev = bswap32(s->c_rdev); |
1511 | s->c_birthtimensec = bswap32(s->c_birthtimensec); | | 1511 | s->c_birthtimensec = bswap32(s->c_birthtimensec); |
1512 | s->c_birthtime = bswap64(s->c_birthtime); | | 1512 | s->c_birthtime = bswap64(s->c_birthtime); |
1513 | s->c_atime = bswap64(s->c_atime); | | 1513 | s->c_atime = bswap64(s->c_atime); |
1514 | s->c_mtime = bswap64(s->c_mtime); | | 1514 | s->c_mtime = bswap64(s->c_mtime); |
1515 | s->c_file_flags = bswap32(s->c_file_flags); | | 1515 | s->c_file_flags = bswap32(s->c_file_flags); |
1516 | s->c_uid = bswap32(s->c_uid); | | 1516 | s->c_uid = bswap32(s->c_uid); |
1517 | s->c_gid = bswap32(s->c_gid); | | 1517 | s->c_gid = bswap32(s->c_gid); |
1518 | | | 1518 | |
1519 | s->c_count = bswap32(s->c_count); | | 1519 | s->c_count = bswap32(s->c_count); |
1520 | s->c_level = bswap32(s->c_level); | | 1520 | s->c_level = bswap32(s->c_level); |
1521 | s->c_flags = bswap32(s->c_flags); | | 1521 | s->c_flags = bswap32(s->c_flags); |
1522 | s->c_old_firstrec = bswap32(s->c_old_firstrec); | | 1522 | s->c_old_firstrec = bswap32(s->c_old_firstrec); |
1523 | | | 1523 | |
1524 | s->c_date = bswap64(s->c_date); | | 1524 | s->c_date = bswap64(s->c_date); |
1525 | s->c_ddate = bswap64(s->c_ddate); | | 1525 | s->c_ddate = bswap64(s->c_ddate); |
1526 | s->c_tapea = bswap64(s->c_tapea); | | 1526 | s->c_tapea = bswap64(s->c_tapea); |
1527 | s->c_firstrec = bswap64(s->c_firstrec); | | 1527 | s->c_firstrec = bswap64(s->c_firstrec); |
1528 | | | 1528 | |
1529 | /* | | 1529 | /* |
1530 | * These are ouid and ogid. | | 1530 | * These are ouid and ogid. |
1531 | */ | | 1531 | */ |
1532 | s->c_spare1[1] = bswap16(s->c_spare1[1]); | | 1532 | s->c_spare1[1] = bswap16(s->c_spare1[1]); |
1533 | s->c_spare1[2] = bswap16(s->c_spare1[2]); | | 1533 | s->c_spare1[2] = bswap16(s->c_spare1[2]); |
1534 | } | | 1534 | } |
1535 | | | 1535 | |
1536 | static void | | 1536 | static void |
1537 | swap_old_header(struct s_ospcl *os) | | 1537 | swap_old_header(struct s_ospcl *os) |
1538 | { | | 1538 | { |
1539 | os->c_type = bswap32(os->c_type); | | 1539 | os->c_type = bswap32(os->c_type); |
1540 | os->c_date = bswap32(os->c_date); | | 1540 | os->c_date = bswap32(os->c_date); |
1541 | os->c_ddate = bswap32(os->c_ddate); | | 1541 | os->c_ddate = bswap32(os->c_ddate); |
1542 | os->c_volume = bswap32(os->c_volume); | | 1542 | os->c_volume = bswap32(os->c_volume); |
1543 | os->c_tapea = bswap32(os->c_tapea); | | 1543 | os->c_tapea = bswap32(os->c_tapea); |
1544 | os->c_inumber = bswap16(os->c_inumber); | | 1544 | os->c_inumber = bswap16(os->c_inumber); |
1545 | os->c_magic = bswap32(os->c_magic); | | 1545 | os->c_magic = bswap32(os->c_magic); |
1546 | os->c_checksum = bswap32(os->c_checksum); | | 1546 | os->c_checksum = bswap32(os->c_checksum); |
1547 | | | 1547 | |
1548 | os->c_odinode.odi_mode = bswap16(os->c_odinode.odi_mode); | | 1548 | os->c_odinode.odi_mode = bswap16(os->c_odinode.odi_mode); |
1549 | os->c_odinode.odi_nlink = bswap16(os->c_odinode.odi_nlink); | | 1549 | os->c_odinode.odi_nlink = bswap16(os->c_odinode.odi_nlink); |
1550 | os->c_odinode.odi_uid = bswap16(os->c_odinode.odi_uid); | | 1550 | os->c_odinode.odi_uid = bswap16(os->c_odinode.odi_uid); |
1551 | os->c_odinode.odi_gid = bswap16(os->c_odinode.odi_gid); | | 1551 | os->c_odinode.odi_gid = bswap16(os->c_odinode.odi_gid); |
1552 | | | 1552 | |
1553 | os->c_odinode.odi_size = bswap32(os->c_odinode.odi_size); | | 1553 | os->c_odinode.odi_size = bswap32(os->c_odinode.odi_size); |
1554 | os->c_odinode.odi_rdev = bswap32(os->c_odinode.odi_rdev); | | 1554 | os->c_odinode.odi_rdev = bswap32(os->c_odinode.odi_rdev); |
1555 | os->c_odinode.odi_atime = bswap32(os->c_odinode.odi_atime); | | 1555 | os->c_odinode.odi_atime = bswap32(os->c_odinode.odi_atime); |
1556 | os->c_odinode.odi_mtime = bswap32(os->c_odinode.odi_mtime); | | 1556 | os->c_odinode.odi_mtime = bswap32(os->c_odinode.odi_mtime); |
1557 | os->c_odinode.odi_ctime = bswap32(os->c_odinode.odi_ctime); | | 1557 | os->c_odinode.odi_ctime = bswap32(os->c_odinode.odi_ctime); |
1558 | | | 1558 | |
1559 | os->c_count = bswap32(os->c_count); | | 1559 | os->c_count = bswap32(os->c_count); |
1560 | } | | 1560 | } |