main.c revision 1.11 1 1.11 reinoud /* $NetBSD: main.c,v 1.11 2022/04/24 15:07:08 reinoud Exp $ */
2 1.1 reinoud
3 1.1 reinoud /*
4 1.1 reinoud * Copyright (c) 2022 Reinoud Zandijk
5 1.1 reinoud * All rights reserved.
6 1.6 riastrad *
7 1.1 reinoud * Redistribution and use in source and binary forms, with or without
8 1.1 reinoud * modification, are permitted provided that the following conditions
9 1.1 reinoud * are met:
10 1.1 reinoud * 1. Redistributions of source code must retain the above copyright
11 1.1 reinoud * notice, this list of conditions and the following disclaimer.
12 1.1 reinoud * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 reinoud * notice, this list of conditions and the following disclaimer in the
14 1.1 reinoud * documentation and/or other materials provided with the distribution.
15 1.6 riastrad *
16 1.1 reinoud * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1 reinoud * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.1 reinoud * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.1 reinoud * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.1 reinoud * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 1.1 reinoud * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 1.1 reinoud * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 1.1 reinoud * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1.1 reinoud * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 1.1 reinoud * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1.6 riastrad *
27 1.1 reinoud */
28 1.1 reinoud
29 1.1 reinoud
30 1.1 reinoud /*
31 1.1 reinoud * Note to reader:
32 1.1 reinoud *
33 1.1 reinoud * fsck_udf uses the common udf_core.c file with newfs and makefs. It does use
34 1.1 reinoud * some of the layout structure values but not all.
35 1.1 reinoud */
36 1.1 reinoud
37 1.1 reinoud
38 1.1 reinoud #include <sys/cdefs.h>
39 1.1 reinoud #ifndef lint
40 1.11 reinoud __RCSID("$NetBSD: main.c,v 1.11 2022/04/24 15:07:08 reinoud Exp $");
41 1.1 reinoud #endif /* not lint */
42 1.1 reinoud
43 1.1 reinoud #include <stdio.h>
44 1.1 reinoud #include <stdlib.h>
45 1.1 reinoud #include <stddef.h>
46 1.1 reinoud #include <dirent.h>
47 1.1 reinoud #include <inttypes.h>
48 1.1 reinoud #include <stdint.h>
49 1.1 reinoud #include <string.h>
50 1.1 reinoud #include <errno.h>
51 1.1 reinoud #include <fcntl.h>
52 1.1 reinoud #include <unistd.h>
53 1.1 reinoud #include <util.h>
54 1.1 reinoud #include <time.h>
55 1.1 reinoud #include <tzfile.h>
56 1.1 reinoud #include <math.h>
57 1.1 reinoud #include <assert.h>
58 1.1 reinoud #include <err.h>
59 1.1 reinoud
60 1.1 reinoud #if !HAVE_NBTOOL_CONFIG_H
61 1.1 reinoud #define _EXPOSE_MMC
62 1.1 reinoud #include <sys/cdio.h>
63 1.1 reinoud #else
64 1.1 reinoud #include "udf/cdio_mmc_structs.h"
65 1.1 reinoud #endif
66 1.1 reinoud
67 1.1 reinoud #include <sys/ioctl.h>
68 1.1 reinoud #include <sys/stat.h>
69 1.1 reinoud #include <sys/types.h>
70 1.1 reinoud #include <sys/disklabel.h>
71 1.1 reinoud #include <sys/dkio.h>
72 1.1 reinoud #include <sys/param.h>
73 1.1 reinoud #include <sys/queue.h>
74 1.1 reinoud
75 1.1 reinoud #include <fs/udf/ecma167-udf.h>
76 1.1 reinoud #include <fs/udf/udf_mount.h>
77 1.1 reinoud
78 1.1 reinoud #include "fsutil.h"
79 1.1 reinoud #include "exitvalues.h"
80 1.1 reinoud #include "udf_core.h"
81 1.1 reinoud
82 1.1 reinoud /* Identifying myself */
83 1.1 reinoud #define IMPL_NAME "*NetBSD fsck_udf 10.0"
84 1.1 reinoud #define APP_VERSION_MAIN 0
85 1.1 reinoud #define APP_VERSION_SUB 5
86 1.1 reinoud
87 1.1 reinoud /* allocation walker actions */
88 1.1 reinoud #define AD_LOAD_FILE (1<<0)
89 1.1 reinoud #define AD_SAVE_FILE (1<<1)
90 1.1 reinoud #define AD_CHECK_FIDS (1<<2)
91 1.1 reinoud #define AD_ADJUST_FIDS (1<<3)
92 1.1 reinoud #define AD_GATHER_STATS (1<<4)
93 1.1 reinoud #define AD_CHECK_USED (1<<5)
94 1.1 reinoud #define AD_MARK_AS_USED (1<<6)
95 1.1 reinoud #define AD_FIND_OVERLAP_PAIR (1<<7)
96 1.1 reinoud
97 1.1 reinoud struct udf_fsck_file_stats {
98 1.1 reinoud uint64_t inf_len;
99 1.1 reinoud uint64_t obj_size;
100 1.1 reinoud uint64_t logblks_rec;
101 1.1 reinoud };
102 1.1 reinoud
103 1.1 reinoud
104 1.1 reinoud struct udf_fsck_fid_context {
105 1.1 reinoud uint64_t fid_offset;
106 1.1 reinoud uint64_t data_left;
107 1.1 reinoud };
108 1.1 reinoud
109 1.1 reinoud
110 1.1 reinoud /* basic node administration for passes */
111 1.1 reinoud #define FSCK_NODE_FLAG_HARDLINK (1<< 0) /* hardlink, for accounting */
112 1.1 reinoud #define FSCK_NODE_FLAG_DIRECTORY (1<< 1) /* is a normal directory */
113 1.1 reinoud #define FSCK_NODE_FLAG_HAS_STREAM_DIR (1<< 2) /* has a stream directory */
114 1.1 reinoud #define FSCK_NODE_FLAG_STREAM_ENTRY (1<< 3) /* is a stream file */
115 1.1 reinoud #define FSCK_NODE_FLAG_STREAM_DIR (1<< 4) /* is a stream directory */
116 1.1 reinoud #define FSCK_NODE_FLAG_OK(f) (((f) >> 5) == 0)
117 1.1 reinoud
118 1.1 reinoud #define FSCK_NODE_FLAG_KEEP (1<< 5) /* don't discard */
119 1.1 reinoud #define FSCK_NODE_FLAG_DIRTY (1<< 6) /* descriptor needs writeout */
120 1.1 reinoud #define FSCK_NODE_FLAG_REPAIRDIR (1<< 7) /* repair bad FID entries */
121 1.1 reinoud #define FSCK_NODE_FLAG_NEW_UNIQUE_ID (1<< 8) /* repair bad FID entries */
122 1.1 reinoud #define FSCK_NODE_FLAG_COPY_PARENT_ID (1<< 9) /* repair bad FID entries */
123 1.1 reinoud #define FSCK_NODE_FLAG_WIPE_STREAM_DIR (1<<10) /* wipe stream directory */
124 1.1 reinoud #define FSCK_NODE_FLAG_NOTFOUND (1<<11) /* FID pointing to garbage */
125 1.1 reinoud #define FSCK_NODE_FLAG_PAR_NOT_FOUND (1<<12) /* parent node not found! */
126 1.1 reinoud #define FSCK_NODE_FLAG_OVERLAP (1<<13) /* node has overlaps */
127 1.1 reinoud
128 1.1 reinoud #define FSCK_NODE_FLAG_STREAM (FSCK_NODE_FLAG_STREAM_ENTRY | FSCK_NODE_FLAG_STREAM_DIR)
129 1.1 reinoud
130 1.1 reinoud
131 1.1 reinoud #define HASH_HASHBITS 5
132 1.1 reinoud #define HASH_HASHSIZE (1 << HASH_HASHBITS)
133 1.1 reinoud #define HASH_HASHMASK (HASH_HASHSIZE - 1)
134 1.1 reinoud
135 1.1 reinoud /* fsck node for accounting checks */
136 1.1 reinoud struct udf_fsck_node {
137 1.1 reinoud struct udf_fsck_node *parent;
138 1.1 reinoud char *fname;
139 1.1 reinoud
140 1.1 reinoud struct long_ad loc;
141 1.1 reinoud struct long_ad streamdir_loc;
142 1.1 reinoud int fsck_flags;
143 1.1 reinoud
144 1.1 reinoud int link_count;
145 1.1 reinoud int found_link_count;
146 1.1 reinoud uint64_t unique_id;
147 1.1 reinoud
148 1.1 reinoud struct udf_fsck_file_stats declared;
149 1.1 reinoud struct udf_fsck_file_stats found;
150 1.1 reinoud
151 1.1 reinoud uint8_t *directory; /* directory contents */
152 1.1 reinoud
153 1.1 reinoud LIST_ENTRY(udf_fsck_node) next_hash;
154 1.1 reinoud TAILQ_ENTRY(udf_fsck_node) next;
155 1.1 reinoud };
156 1.1 reinoud TAILQ_HEAD(udf_fsck_node_list, udf_fsck_node) fs_nodes;
157 1.1 reinoud LIST_HEAD(udf_fsck_node_hash_list, udf_fsck_node) fs_nodes_hash[HASH_HASHSIZE];
158 1.1 reinoud
159 1.1 reinoud
160 1.1 reinoud /* fsck used space bitmap conflict list */
161 1.1 reinoud #define FSCK_OVERLAP_MAIN_NODE (1<<0)
162 1.1 reinoud #define FSCK_OVERLAP_EXTALLOC (1<<1)
163 1.1 reinoud #define FSCK_OVERLAP_EXTENT (1<<2)
164 1.1 reinoud
165 1.1 reinoud struct udf_fsck_overlap {
166 1.1 reinoud struct udf_fsck_node *node;
167 1.1 reinoud struct udf_fsck_node *node2;
168 1.1 reinoud
169 1.1 reinoud struct long_ad loc;
170 1.1 reinoud struct long_ad loc2;
171 1.1 reinoud
172 1.1 reinoud int flags;
173 1.1 reinoud int flags2;
174 1.1 reinoud
175 1.1 reinoud TAILQ_ENTRY(udf_fsck_overlap) next;
176 1.1 reinoud };
177 1.1 reinoud TAILQ_HEAD(udf_fsck_overlap_list, udf_fsck_overlap) fsck_overlaps;
178 1.1 reinoud
179 1.1 reinoud
180 1.1 reinoud /* backup of old read in free space bitmaps */
181 1.1 reinoud struct space_bitmap_desc *recorded_part_unalloc_bits[UDF_PARTITIONS];
182 1.1 reinoud uint32_t recorded_part_free[UDF_PARTITIONS];
183 1.1 reinoud
184 1.1 reinoud /* shadow VAT build */
185 1.1 reinoud uint8_t *shadow_vat_contents;
186 1.1 reinoud
187 1.1 reinoud
188 1.1 reinoud /* options */
189 1.1 reinoud int alwaysno = 0; /* assume "no" for all questions */
190 1.1 reinoud int alwaysyes = 0; /* assume "yes" for all questions */
191 1.1 reinoud int search_older_vat = 0; /* search for older VATs */
192 1.1 reinoud int force = 0; /* do check even if its marked clean */
193 1.1 reinoud int preen = 0; /* set when preening, doing automatic small repairs */
194 1.1 reinoud int rdonly = 0; /* open device/image read-only */
195 1.1 reinoud int rdonly_flag = 0; /* as passed on command line */
196 1.1 reinoud int heuristics = 0; /* use heuristics to fix esoteric corruptions */
197 1.1 reinoud int target_session = 0; /* offset to last session to check */
198 1.1 reinoud
199 1.1 reinoud
200 1.1 reinoud /* actions to undertake */
201 1.1 reinoud int undo_opening_session = 0; /* trying to undo opening of last crippled session */
202 1.1 reinoud int open_integrity = 0; /* should be open the integrity ie close later */
203 1.1 reinoud int vat_writeout = 0; /* write out the VAT anyway */
204 1.1 reinoud
205 1.1 reinoud
206 1.1 reinoud /* SIGINFO */
207 1.1 reinoud static sig_atomic_t print_info = 0; /* request for information on progress */
208 1.1 reinoud
209 1.1 reinoud
210 1.1 reinoud /* prototypes */
211 1.1 reinoud static void usage(void) __dead;
212 1.1 reinoud static int checkfilesys(char *given_dev);
213 1.1 reinoud static int ask(int def, const char *fmt, ...);
214 1.1 reinoud static int ask_noauto(int def, const char *fmt, ...);
215 1.1 reinoud
216 1.1 reinoud static void udf_recursive_keep(struct udf_fsck_node *node);
217 1.1 reinoud static char *udf_node_path(struct udf_fsck_node *node);
218 1.1 reinoud static void udf_shadow_VAT_in_use(struct long_ad *loc);
219 1.1 reinoud static int udf_quick_check_fids(struct udf_fsck_node *node, union dscrptr *dscr);
220 1.1 reinoud
221 1.1 reinoud
222 1.1 reinoud /* --------------------------------------------------------------------- */
223 1.1 reinoud
224 1.1 reinoud /* from bin/ls */
225 1.1 reinoud static void
226 1.1 reinoud printtime(time_t ftime)
227 1.1 reinoud {
228 1.1 reinoud struct timespec clock;
229 1.1 reinoud const char *longstring;
230 1.1 reinoud time_t now;
231 1.1 reinoud int i;
232 1.1 reinoud
233 1.1 reinoud clock_gettime(CLOCK_REALTIME, &clock);
234 1.1 reinoud now = clock.tv_sec;
235 1.1 reinoud
236 1.1 reinoud if ((longstring = ctime(&ftime)) == NULL) {
237 1.1 reinoud /* 012345678901234567890123 */
238 1.1 reinoud longstring = "????????????????????????";
239 1.1 reinoud }
240 1.1 reinoud for (i = 4; i < 11; ++i)
241 1.1 reinoud (void)putchar(longstring[i]);
242 1.1 reinoud
243 1.1 reinoud #define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
244 1.1 reinoud if (ftime + SIXMONTHS > now && ftime - SIXMONTHS < now)
245 1.1 reinoud for (i = 11; i < 16; ++i)
246 1.1 reinoud (void)putchar(longstring[i]);
247 1.1 reinoud else {
248 1.1 reinoud (void)putchar(' ');
249 1.1 reinoud for (i = 20; i < 24; ++i)
250 1.1 reinoud (void)putchar(longstring[i]);
251 1.1 reinoud }
252 1.1 reinoud (void)putchar(' ');
253 1.1 reinoud }
254 1.1 reinoud
255 1.1 reinoud
256 1.1 reinoud static void
257 1.1 reinoud udf_print_timestamp(const char *prefix, struct timestamp *timestamp, const char *suffix)
258 1.1 reinoud {
259 1.1 reinoud struct timespec timespec;
260 1.1 reinoud
261 1.1 reinoud udf_timestamp_to_timespec(timestamp, ×pec);
262 1.1 reinoud printf("%s", prefix);
263 1.1 reinoud printtime(timespec.tv_sec);
264 1.1 reinoud printf("%s", suffix);
265 1.1 reinoud }
266 1.1 reinoud
267 1.1 reinoud
268 1.1 reinoud static int
269 1.1 reinoud udf_compare_mtimes(struct timestamp *t1, struct timestamp *t2)
270 1.1 reinoud {
271 1.1 reinoud struct timespec t1_tsp, t2_tsp;
272 1.1 reinoud
273 1.1 reinoud udf_timestamp_to_timespec(t1, &t1_tsp);
274 1.1 reinoud udf_timestamp_to_timespec(t2, &t2_tsp);
275 1.1 reinoud
276 1.1 reinoud if (t1_tsp.tv_sec < t2_tsp.tv_sec)
277 1.1 reinoud return -1;
278 1.1 reinoud if (t1_tsp.tv_sec > t2_tsp.tv_sec)
279 1.1 reinoud return 1;
280 1.1 reinoud if (t1_tsp.tv_nsec < t2_tsp.tv_nsec)
281 1.1 reinoud return -1;
282 1.1 reinoud if (t1_tsp.tv_nsec > t2_tsp.tv_nsec)
283 1.1 reinoud return 1;
284 1.1 reinoud return 0;
285 1.1 reinoud }
286 1.1 reinoud
287 1.1 reinoud /* --------------------------------------------------------------------- */
288 1.1 reinoud
289 1.1 reinoud static int
290 1.1 reinoud udf_calc_node_hash(struct long_ad *icb)
291 1.1 reinoud {
292 1.1 reinoud uint32_t lb_num = udf_rw32(icb->loc.lb_num);
293 1.1 reinoud uint16_t vpart = udf_rw16(icb->loc.part_num);
294 1.1 reinoud
295 1.1 reinoud return ((uint64_t) (vpart + lb_num * 257)) & HASH_HASHMASK;
296 1.1 reinoud }
297 1.1 reinoud
298 1.1 reinoud
299 1.1 reinoud static struct udf_fsck_node *
300 1.1 reinoud udf_node_lookup(struct long_ad *icb)
301 1.1 reinoud {
302 1.1 reinoud struct udf_fsck_node *pos;
303 1.1 reinoud int entry = udf_calc_node_hash(icb);
304 1.1 reinoud
305 1.1 reinoud pos = LIST_FIRST(&fs_nodes_hash[entry]);
306 1.1 reinoud while (pos) {
307 1.1 reinoud if (pos->loc.loc.part_num == icb->loc.part_num)
308 1.1 reinoud if (pos->loc.loc.lb_num == icb->loc.lb_num)
309 1.1 reinoud return pos;
310 1.1 reinoud pos = LIST_NEXT(pos, next_hash);
311 1.1 reinoud }
312 1.1 reinoud return NULL;
313 1.1 reinoud }
314 1.1 reinoud
315 1.1 reinoud /* --------------------------------------------------------------------- */
316 1.1 reinoud
317 1.1 reinoud /* Note: only for VAT media since we don't allocate in bitmap */
318 1.1 reinoud static void
319 1.1 reinoud udf_wipe_and_reallocate(union dscrptr *dscrptr, int vpart_num, uint32_t *l_adp)
320 1.1 reinoud {
321 1.1 reinoud struct file_entry *fe = &dscrptr->fe;
322 1.1 reinoud struct extfile_entry *efe = &dscrptr->efe;
323 1.1 reinoud struct desc_tag *tag = &dscrptr->tag;
324 1.1 reinoud struct icb_tag *icb;
325 1.1 reinoud struct long_ad allocated;
326 1.1 reinoud struct long_ad *long_adp = NULL;
327 1.1 reinoud struct short_ad *short_adp = NULL;
328 1.1 reinoud uint64_t inf_len;
329 1.1 reinoud uint32_t l_ea, l_ad;
330 1.1 reinoud uint8_t *bpos;
331 1.1 reinoud int bpos_start, ad_type, id;
332 1.1 reinoud
333 1.1 reinoud assert(context.format_flags & FORMAT_VAT);
334 1.1 reinoud
335 1.1 reinoud id = udf_rw16(tag->id);
336 1.1 reinoud assert(id == TAGID_FENTRY || id == TAGID_EXTFENTRY);
337 1.1 reinoud if (id == TAGID_FENTRY) {
338 1.1 reinoud icb = &fe->icbtag;
339 1.1 reinoud inf_len = udf_rw64(fe->inf_len);
340 1.1 reinoud l_ea = udf_rw32(fe->l_ea);
341 1.1 reinoud bpos = (uint8_t *) fe->data + l_ea;
342 1.1 reinoud bpos_start = offsetof(struct file_entry, data) + l_ea;
343 1.1 reinoud } else {
344 1.1 reinoud icb = &efe->icbtag;
345 1.1 reinoud inf_len = udf_rw64(efe->inf_len);
346 1.1 reinoud l_ea = udf_rw32(efe->l_ea);
347 1.1 reinoud bpos = (uint8_t *) efe->data + l_ea;
348 1.1 reinoud bpos_start = offsetof(struct extfile_entry, data) + l_ea;
349 1.1 reinoud }
350 1.1 reinoud /* inf_len should be correct for one slot */
351 1.1 reinoud assert(inf_len < UDF_EXT_MAXLEN);
352 1.1 reinoud
353 1.1 reinoud ad_type = udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
354 1.1 reinoud if (ad_type == UDF_ICB_INTERN_ALLOC) {
355 1.1 reinoud /* no action needed */
356 1.1 reinoud return;
357 1.1 reinoud }
358 1.1 reinoud
359 1.1 reinoud assert(vpart_num == context.data_part);
360 1.1 reinoud udf_data_alloc(udf_bytes_to_sectors(inf_len), &allocated);
361 1.1 reinoud memset(bpos, 0, context.sector_size - bpos_start);
362 1.1 reinoud /* create one short_ad or one long_ad */
363 1.1 reinoud if (ad_type == UDF_ICB_SHORT_ALLOC) {
364 1.1 reinoud short_adp = (struct short_ad *) bpos;
365 1.8 reinoud short_adp->len = udf_rw32(inf_len);
366 1.1 reinoud short_adp->lb_num = allocated.loc.lb_num;
367 1.1 reinoud l_ad = sizeof(struct short_ad);
368 1.1 reinoud } else {
369 1.1 reinoud long_adp = (struct long_ad *) bpos;
370 1.1 reinoud memcpy(long_adp, &allocated, sizeof(struct long_ad));
371 1.8 reinoud long_adp->len = udf_rw32(inf_len);
372 1.1 reinoud l_ad = sizeof(struct long_ad);
373 1.1 reinoud }
374 1.1 reinoud if (id == TAGID_FENTRY)
375 1.1 reinoud fe->l_ad = udf_rw32(l_ad);
376 1.1 reinoud else
377 1.1 reinoud efe->l_ad = udf_rw32(l_ad);
378 1.1 reinoud ;
379 1.1 reinoud *l_adp = l_ad;
380 1.1 reinoud }
381 1.1 reinoud
382 1.1 reinoud
383 1.1 reinoud static void
384 1.1 reinoud udf_copy_fid_verbatim(struct fileid_desc *sfid, struct fileid_desc *dfid,
385 1.1 reinoud uint64_t dfpos, uint64_t drest)
386 1.1 reinoud {
387 1.1 reinoud uint64_t endfid;
388 1.1 reinoud uint32_t minlen, lb_rest, fidsize;
389 1.1 reinoud
390 1.1 reinoud if (udf_rw16(sfid->l_iu) == 0) {
391 1.1 reinoud memcpy(dfid, sfid, udf_fidsize(sfid));
392 1.1 reinoud return;
393 1.1 reinoud }
394 1.1 reinoud
395 1.1 reinoud /* see if we can reduce its size */
396 1.1 reinoud minlen = udf_fidsize(sfid) - udf_rw16(sfid->l_iu);
397 1.1 reinoud
398 1.1 reinoud /*
399 1.1 reinoud * OK, tricky part: we need to pad so the next descriptor header won't
400 1.1 reinoud * cross the sector boundary
401 1.1 reinoud */
402 1.1 reinoud endfid = dfpos + minlen;
403 1.1 reinoud lb_rest = context.sector_size - (endfid % context.sector_size);
404 1.1 reinoud
405 1.1 reinoud memcpy(dfid, sfid, UDF_FID_SIZE);
406 1.1 reinoud if (lb_rest < sizeof(struct desc_tag)) {
407 1.1 reinoud /* add at least 32 */
408 1.1 reinoud dfid->l_iu = udf_rw16(32);
409 1.1 reinoud udf_set_regid((struct regid *) dfid->data, context.impl_name);
410 1.1 reinoud udf_add_impl_regid((struct regid *) dfid->data);
411 1.1 reinoud
412 1.1 reinoud }
413 1.1 reinoud memcpy( dfid->data + udf_rw16(dfid->l_iu),
414 1.1 reinoud sfid->data + udf_rw16(sfid->l_iu),
415 1.1 reinoud minlen - UDF_FID_SIZE);
416 1.1 reinoud
417 1.1 reinoud fidsize = udf_fidsize(dfid);
418 1.1 reinoud dfid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
419 1.1 reinoud }
420 1.1 reinoud
421 1.1 reinoud
422 1.1 reinoud static int
423 1.1 reinoud udf_rebuild_fid_stream(struct udf_fsck_node *node, int64_t *rest_lenp)
424 1.1 reinoud {
425 1.1 reinoud struct fileid_desc *sfid, *dfid;
426 1.1 reinoud uint64_t inf_len;
427 1.1 reinoud uint64_t sfpos, dfpos;
428 1.1 reinoud int64_t srest, drest;
429 1.1 reinoud // uint32_t sfid_len, dfid_len;
430 1.1 reinoud uint8_t *directory, *rebuild_dir;
431 1.1 reinoud // int namelen;
432 1.1 reinoud int error, streaming, was_streaming, warned, error_in_stream;
433 1.1 reinoud
434 1.1 reinoud directory = node->directory;
435 1.1 reinoud inf_len = node->found.inf_len;
436 1.1 reinoud
437 1.1 reinoud rebuild_dir = calloc(1, inf_len);
438 1.1 reinoud assert(rebuild_dir);
439 1.1 reinoud
440 1.1 reinoud sfpos = 0;
441 1.1 reinoud srest = inf_len;
442 1.1 reinoud
443 1.1 reinoud dfpos = 0;
444 1.1 reinoud drest = inf_len;
445 1.1 reinoud
446 1.1 reinoud error_in_stream = 0;
447 1.1 reinoud streaming = 1;
448 1.1 reinoud was_streaming = 1;
449 1.1 reinoud warned = 0;
450 1.1 reinoud while (srest > 0) {
451 1.1 reinoud if (was_streaming & !streaming) {
452 1.1 reinoud if (!warned) {
453 1.1 reinoud pwarn("%s : BROKEN directory\n",
454 1.1 reinoud udf_node_path(node));
455 1.1 reinoud udf_recursive_keep(node);
456 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
457 1.1 reinoud }
458 1.1 reinoud warned = 1;
459 1.1 reinoud pwarn("%s : <directory resync>\n",
460 1.1 reinoud udf_node_path(node));
461 1.1 reinoud }
462 1.1 reinoud was_streaming = streaming;
463 1.1 reinoud
464 1.1 reinoud assert(drest >= UDF_FID_SIZE);
465 1.1 reinoud sfid = (struct fileid_desc *) (directory + sfpos);
466 1.1 reinoud dfid = (struct fileid_desc *) (rebuild_dir + dfpos);
467 1.1 reinoud
468 1.1 reinoud /* check if we can read/salvage the next source fid */
469 1.1 reinoud if (udf_rw16(sfid->tag.id) != TAGID_FID) {
470 1.1 reinoud streaming = 0;
471 1.1 reinoud sfpos += 4;
472 1.1 reinoud srest -= 4;
473 1.1 reinoud error_in_stream = 1;
474 1.1 reinoud continue;
475 1.1 reinoud }
476 1.1 reinoud error = udf_check_tag(sfid);
477 1.1 reinoud if (error) {
478 1.1 reinoud /* unlikely to be recoverable */
479 1.1 reinoud streaming = 0;
480 1.1 reinoud sfpos += 4;
481 1.1 reinoud srest -= 4;
482 1.1 reinoud error_in_stream = 1;
483 1.1 reinoud continue;
484 1.1 reinoud }
485 1.1 reinoud error = udf_check_tag_payload(
486 1.1 reinoud (union dscrptr *) sfid,
487 1.1 reinoud context.sector_size);
488 1.1 reinoud if (!error) {
489 1.1 reinoud streaming = 1;
490 1.1 reinoud /* all OK, just copy verbatim, shrinking if possible */
491 1.1 reinoud udf_copy_fid_verbatim(sfid, dfid, dfpos, drest);
492 1.1 reinoud
493 1.1 reinoud sfpos += udf_fidsize(sfid);
494 1.1 reinoud srest -= udf_fidsize(sfid);
495 1.1 reinoud
496 1.1 reinoud dfpos += udf_fidsize(dfid);
497 1.1 reinoud drest -= udf_fidsize(dfid);
498 1.1 reinoud
499 1.1 reinoud assert(udf_fidsize(sfid) == udf_fidsize(dfid));
500 1.1 reinoud continue;
501 1.1 reinoud }
502 1.1 reinoud
503 1.1 reinoud /*
504 1.1 reinoud * The hard part, we need to try to recover of what is
505 1.1 reinoud * deductible of the bad source fid. The tag itself is OK, but
506 1.1 reinoud * that doesn't say much; its contents can still be off.
507 1.1 reinoud */
508 1.1 reinoud
509 1.1 reinoud /* TODO NOT IMPLEMENTED YET, skip this entry the blunt way */
510 1.1 reinoud streaming = 0;
511 1.1 reinoud sfpos += 4;
512 1.1 reinoud srest -= 4;
513 1.1 reinoud error_in_stream = 1;
514 1.1 reinoud }
515 1.1 reinoud
516 1.1 reinoud /* if we could shrink/fix the node, mark it for repair */
517 1.1 reinoud if (error_in_stream) {
518 1.1 reinoud udf_recursive_keep(node);
519 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
520 1.1 reinoud }
521 1.1 reinoud
522 1.1 reinoud if (sfpos != dfpos)
523 1.3 martin printf("%s: could save %" PRIi64 " bytes in directory\n", udf_node_path(node), sfpos - dfpos);
524 1.1 reinoud
525 1.1 reinoud memset(directory, 0, inf_len);
526 1.1 reinoud memcpy(directory, rebuild_dir, dfpos);
527 1.1 reinoud
528 1.1 reinoud free(rebuild_dir);
529 1.1 reinoud
530 1.1 reinoud *rest_lenp = dfpos;
531 1.1 reinoud return error_in_stream;
532 1.1 reinoud }
533 1.1 reinoud
534 1.1 reinoud
535 1.1 reinoud static int
536 1.1 reinoud udf_quick_check_fids_piece(uint8_t *piece, uint32_t piece_len,
537 1.1 reinoud struct udf_fsck_fid_context *fid_context,
538 1.1 reinoud uint32_t lb_num)
539 1.1 reinoud {
540 1.1 reinoud int error;
541 1.1 reinoud struct fileid_desc *fid;
542 1.1 reinoud uint32_t location;
543 1.1 reinoud uint32_t offset, fidsize;
544 1.1 reinoud
545 1.1 reinoud offset = fid_context->fid_offset % context.sector_size;
546 1.1 reinoud while (fid_context->data_left && (offset < piece_len)) {
547 1.1 reinoud fid = (struct fileid_desc *) (piece + offset);
548 1.1 reinoud if (udf_rw16(fid->tag.id) == TAGID_FID) {
549 1.1 reinoud error = udf_check_tag_payload(
550 1.1 reinoud (union dscrptr *) fid,
551 1.1 reinoud context.sector_size);
552 1.1 reinoud if (error)
553 1.1 reinoud return error;
554 1.1 reinoud } else {
555 1.1 reinoud return EINVAL;
556 1.1 reinoud }
557 1.1 reinoud assert(udf_rw16(fid->tag.id) == TAGID_FID);
558 1.1 reinoud
559 1.1 reinoud location = lb_num + offset / context.sector_size;
560 1.1 reinoud
561 1.1 reinoud if (udf_rw32(fid->tag.tag_loc) != location)
562 1.1 reinoud return EINVAL;
563 1.1 reinoud
564 1.1 reinoud if (context.dscrver == 2) {
565 1.1 reinoud /* compression IDs should be preserved in UDF < 2.00 */
566 1.1 reinoud if (*(fid->data + udf_rw16(fid->l_iu)) > 16)
567 1.1 reinoud return EINVAL;
568 1.1 reinoud }
569 1.1 reinoud
570 1.1 reinoud fidsize = udf_fidsize(fid);
571 1.1 reinoud offset += fidsize;
572 1.1 reinoud fid_context->fid_offset += fidsize;
573 1.1 reinoud fid_context->data_left -= fidsize;
574 1.1 reinoud }
575 1.1 reinoud
576 1.1 reinoud return 0;
577 1.1 reinoud }
578 1.1 reinoud
579 1.1 reinoud
580 1.1 reinoud static void
581 1.1 reinoud udf_fids_fixup(uint8_t *piece, uint32_t piece_len,
582 1.1 reinoud struct udf_fsck_fid_context *fid_context,
583 1.1 reinoud uint32_t lb_num)
584 1.1 reinoud {
585 1.1 reinoud struct fileid_desc *fid;
586 1.1 reinoud uint32_t location;
587 1.1 reinoud uint32_t offset, fidsize;
588 1.1 reinoud
589 1.1 reinoud offset = fid_context->fid_offset % context.sector_size;
590 1.1 reinoud while (fid_context->data_left && (offset < piece_len)) {
591 1.1 reinoud
592 1.1 reinoud fid = (struct fileid_desc *) (piece + offset);
593 1.1 reinoud assert(udf_rw16(fid->tag.id) == TAGID_FID);
594 1.1 reinoud
595 1.1 reinoud location = lb_num + offset / context.sector_size;
596 1.1 reinoud fid->tag.tag_loc = udf_rw32(location);
597 1.1 reinoud
598 1.1 reinoud udf_validate_tag_and_crc_sums((union dscrptr *) fid);
599 1.1 reinoud
600 1.1 reinoud fidsize = udf_fidsize(fid);
601 1.1 reinoud offset += fidsize;
602 1.1 reinoud fid_context->fid_offset += fidsize;
603 1.1 reinoud fid_context->data_left -= fidsize;
604 1.1 reinoud }
605 1.1 reinoud }
606 1.1 reinoud
607 1.1 reinoud
608 1.1 reinoud /* NOTE returns non 0 for overlap, not an error code */
609 1.1 reinoud static int
610 1.1 reinoud udf_check_if_allocated(struct udf_fsck_node *node, int flags,
611 1.1 reinoud uint32_t start_lb, int partnr, uint32_t piece_len)
612 1.1 reinoud {
613 1.1 reinoud union dscrptr *dscr;
614 1.1 reinoud struct udf_fsck_overlap *new_overlap;
615 1.1 reinoud uint8_t *bpos;
616 1.1 reinoud uint32_t cnt, bit;
617 1.1 reinoud uint32_t blocks = udf_bytes_to_sectors(piece_len);
618 1.1 reinoud int overlap = 0;
619 1.1 reinoud
620 1.1 reinoud /* account for space used on underlying partition */
621 1.1 reinoud #ifdef DEBUG
622 1.1 reinoud printf("check allocated : node %p, flags %d, partnr %d, start_lb %d for %d blocks\n",
623 1.1 reinoud node, flags, partnr, start_lb, blocks);
624 1.1 reinoud #endif
625 1.1 reinoud
626 1.1 reinoud switch (context.vtop_tp[partnr]) {
627 1.1 reinoud case UDF_VTOP_TYPE_VIRT:
628 1.1 reinoud /* nothing */
629 1.1 reinoud break;
630 1.1 reinoud case UDF_VTOP_TYPE_PHYS:
631 1.1 reinoud case UDF_VTOP_TYPE_SPAREABLE:
632 1.1 reinoud case UDF_VTOP_TYPE_META:
633 1.1 reinoud if (context.part_unalloc_bits[context.vtop[partnr]] == NULL)
634 1.1 reinoud break;
635 1.1 reinoud #ifdef DEBUG
636 1.1 reinoud printf("checking allocation of %d+%d for being used\n", start_lb, blocks);
637 1.1 reinoud #endif
638 1.1 reinoud dscr = (union dscrptr *) (context.part_unalloc_bits[partnr]);
639 1.1 reinoud for (cnt = start_lb; cnt < start_lb + blocks; cnt++) {
640 1.1 reinoud bpos = &dscr->sbd.data[cnt / 8];
641 1.1 reinoud bit = cnt % 8;
642 1.1 reinoud /* only account for bits marked free */
643 1.1 reinoud if ((*bpos & (1 << bit)) == 0)
644 1.1 reinoud overlap++;
645 1.1 reinoud }
646 1.1 reinoud if (overlap == 0)
647 1.1 reinoud break;
648 1.1 reinoud
649 1.1 reinoud /* overlap */
650 1.1 reinoud // pwarn("%s allocation OVERLAP found, type %d\n",
651 1.1 reinoud // udf_node_path(node), flags);
652 1.1 reinoud udf_recursive_keep(node);
653 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_OVERLAP;
654 1.1 reinoud
655 1.1 reinoud new_overlap = calloc(1, sizeof(struct udf_fsck_overlap));
656 1.1 reinoud assert(new_overlap);
657 1.1 reinoud
658 1.1 reinoud new_overlap->node = node;
659 1.1 reinoud new_overlap->node2 = NULL;
660 1.1 reinoud new_overlap->flags = flags;
661 1.1 reinoud new_overlap->flags2 = 0;
662 1.1 reinoud new_overlap->loc.len = udf_rw32(piece_len);
663 1.1 reinoud new_overlap->loc.loc.lb_num = udf_rw32(start_lb);
664 1.1 reinoud new_overlap->loc.loc.part_num = udf_rw16(partnr);
665 1.1 reinoud
666 1.1 reinoud TAILQ_INSERT_TAIL(&fsck_overlaps, new_overlap, next);
667 1.1 reinoud
668 1.1 reinoud return overlap;
669 1.1 reinoud break;
670 1.1 reinoud default:
671 1.1 reinoud errx(1, "internal error: bad mapping type %d in %s",
672 1.1 reinoud context.vtop_tp[partnr], __func__);
673 1.1 reinoud }
674 1.1 reinoud /* no overlap */
675 1.1 reinoud return 0;
676 1.1 reinoud }
677 1.1 reinoud
678 1.1 reinoud
679 1.1 reinoud /* NOTE returns non 0 for overlap, not an error code */
680 1.1 reinoud static void
681 1.1 reinoud udf_check_overlap_pair(struct udf_fsck_node *node, int flags,
682 1.1 reinoud uint32_t start_lb, int partnr, uint32_t piece_len)
683 1.1 reinoud {
684 1.1 reinoud struct udf_fsck_overlap *overlap;
685 1.1 reinoud uint32_t ostart_lb, opiece_len, oblocks;
686 1.1 reinoud uint32_t blocks = udf_bytes_to_sectors(piece_len);
687 1.1 reinoud int opartnr;
688 1.1 reinoud
689 1.1 reinoud /* account for space used on underlying partition */
690 1.1 reinoud #ifdef DEBUG
691 1.1 reinoud printf("check overlap pair : node %p, flags %d, partnr %d, start_lb %d for %d blocks\n",
692 1.1 reinoud node, flags, partnr, start_lb, blocks);
693 1.1 reinoud #endif
694 1.1 reinoud
695 1.1 reinoud switch (context.vtop_tp[partnr]) {
696 1.1 reinoud case UDF_VTOP_TYPE_VIRT:
697 1.1 reinoud /* nothing */
698 1.1 reinoud break;
699 1.1 reinoud case UDF_VTOP_TYPE_PHYS:
700 1.1 reinoud case UDF_VTOP_TYPE_SPAREABLE:
701 1.1 reinoud case UDF_VTOP_TYPE_META:
702 1.1 reinoud if (context.part_unalloc_bits[context.vtop[partnr]] == NULL)
703 1.1 reinoud break;
704 1.1 reinoud #ifdef DEBUG
705 1.1 reinoud printf("checking overlap of %d+%d for being used\n", start_lb, blocks);
706 1.1 reinoud #endif
707 1.1 reinoud /* check all current overlaps with the piece we have here */
708 1.1 reinoud TAILQ_FOREACH(overlap, &fsck_overlaps, next) {
709 1.1 reinoud opiece_len = udf_rw32(overlap->loc.len);
710 1.1 reinoud ostart_lb = udf_rw32(overlap->loc.loc.lb_num);
711 1.1 reinoud opartnr = udf_rw16(overlap->loc.loc.part_num);
712 1.1 reinoud oblocks = udf_bytes_to_sectors(opiece_len);
713 1.1 reinoud
714 1.1 reinoud if (partnr != opartnr)
715 1.1 reinoud continue;
716 1.1 reinoud /* piece before overlap? */
717 1.1 reinoud if (start_lb + blocks < ostart_lb)
718 1.1 reinoud continue;
719 1.1 reinoud /* piece after overlap? */
720 1.1 reinoud if (start_lb > ostart_lb + oblocks)
721 1.1 reinoud continue;
722 1.1 reinoud
723 1.1 reinoud /* overlap, mark conflict */
724 1.1 reinoud overlap->node2 = node;
725 1.1 reinoud overlap->flags2 = flags;
726 1.1 reinoud overlap->loc2.len = udf_rw32(piece_len);
727 1.1 reinoud overlap->loc2.loc.lb_num = udf_rw32(start_lb);
728 1.1 reinoud overlap->loc2.loc.part_num = udf_rw16(partnr);
729 1.1 reinoud
730 1.1 reinoud udf_recursive_keep(node);
731 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_OVERLAP;
732 1.1 reinoud }
733 1.1 reinoud return;
734 1.1 reinoud default:
735 1.1 reinoud errx(1, "internal error: bad mapping type %d in %s",
736 1.1 reinoud context.vtop_tp[partnr], __func__);
737 1.1 reinoud }
738 1.1 reinoud /* no overlap */
739 1.1 reinoud return;
740 1.1 reinoud }
741 1.1 reinoud
742 1.1 reinoud
743 1.1 reinoud
744 1.1 reinoud static int
745 1.1 reinoud udf_process_ad(union dscrptr *dscrptr, int action, uint8_t **resultp,
746 1.1 reinoud int vpart_num, uint64_t fpos,
747 1.1 reinoud struct short_ad *short_adp, struct long_ad *long_adp, void *process_context)
748 1.1 reinoud {
749 1.1 reinoud struct file_entry *fe = &dscrptr->fe;
750 1.1 reinoud struct extfile_entry *efe = &dscrptr->efe;
751 1.1 reinoud struct desc_tag *tag = &dscrptr->tag;
752 1.1 reinoud struct icb_tag *icb;
753 1.1 reinoud struct udf_fsck_file_stats *stats;
754 1.1 reinoud uint64_t inf_len;
755 1.1 reinoud uint32_t l_ea, piece_len, piece_alloc_len, piece_sectors, lb_num, flags;
756 1.1 reinoud uint32_t dscr_lb_num;
757 1.1 reinoud uint32_t i;
758 1.1 reinoud uint8_t *bpos, *piece;
759 1.1 reinoud int id, ad_type;
760 1.1 reinoud int error, piece_error, return_error;
761 1.1 reinoud
762 1.1 reinoud assert(dscrptr);
763 1.1 reinoud stats = (struct udf_fsck_file_stats *) process_context;
764 1.1 reinoud
765 1.1 reinoud id = udf_rw16(tag->id);
766 1.1 reinoud assert(id == TAGID_FENTRY || id == TAGID_EXTFENTRY);
767 1.1 reinoud if (id == TAGID_FENTRY) {
768 1.1 reinoud icb = &fe->icbtag;
769 1.1 reinoud dscr_lb_num = udf_rw32(fe->tag.tag_loc);
770 1.1 reinoud inf_len = udf_rw64(fe->inf_len);
771 1.1 reinoud l_ea = udf_rw32(fe->l_ea);
772 1.1 reinoud bpos = (uint8_t *) fe->data + l_ea;
773 1.1 reinoud } else {
774 1.1 reinoud icb = &efe->icbtag;
775 1.1 reinoud dscr_lb_num = udf_rw32(efe->tag.tag_loc);
776 1.1 reinoud inf_len = udf_rw64(efe->inf_len);
777 1.1 reinoud l_ea = udf_rw32(efe->l_ea);
778 1.1 reinoud bpos = (uint8_t *) efe->data + l_ea;
779 1.1 reinoud }
780 1.1 reinoud
781 1.1 reinoud lb_num = 0;
782 1.1 reinoud piece_len = 0;
783 1.1 reinoud
784 1.1 reinoud ad_type = udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
785 1.1 reinoud if (ad_type == UDF_ICB_INTERN_ALLOC) {
786 1.1 reinoud piece_len = inf_len;
787 1.1 reinoud }
788 1.1 reinoud if (short_adp) {
789 1.1 reinoud piece_len = udf_rw32(short_adp->len);
790 1.1 reinoud lb_num = udf_rw32(short_adp->lb_num);
791 1.1 reinoud }
792 1.1 reinoud if (long_adp) {
793 1.1 reinoud piece_len = udf_rw32(long_adp->len);
794 1.1 reinoud lb_num = udf_rw32(long_adp->loc.lb_num);
795 1.1 reinoud vpart_num = udf_rw16(long_adp->loc.part_num);
796 1.1 reinoud }
797 1.1 reinoud flags = UDF_EXT_FLAGS(piece_len);
798 1.1 reinoud piece_len = UDF_EXT_LEN(piece_len);
799 1.1 reinoud piece_alloc_len = UDF_ROUNDUP(piece_len, context.sector_size);
800 1.1 reinoud piece_sectors = piece_alloc_len / context.sector_size;
801 1.1 reinoud
802 1.1 reinoud return_error = 0;
803 1.1 reinoud if (action & AD_GATHER_STATS) {
804 1.1 reinoud if (ad_type == UDF_ICB_INTERN_ALLOC) {
805 1.1 reinoud stats->inf_len = piece_len;
806 1.1 reinoud stats->obj_size = piece_len;
807 1.1 reinoud stats->logblks_rec = 0;
808 1.1 reinoud } else if (flags == UDF_EXT_ALLOCATED) {
809 1.1 reinoud stats->inf_len += piece_len;
810 1.1 reinoud stats->obj_size += piece_len;
811 1.1 reinoud stats->logblks_rec += piece_sectors;
812 1.1 reinoud } else if (flags == UDF_EXT_FREED) {
813 1.1 reinoud stats->inf_len += piece_len;
814 1.1 reinoud stats->obj_size += piece_len;
815 1.1 reinoud stats->logblks_rec += piece_sectors;
816 1.1 reinoud } else if (flags == UDF_EXT_FREE) {
817 1.1 reinoud stats->inf_len += piece_len;
818 1.1 reinoud stats->obj_size += piece_len;
819 1.1 reinoud }
820 1.1 reinoud }
821 1.1 reinoud if (action & AD_LOAD_FILE) {
822 1.1 reinoud uint32_t alloc_len;
823 1.1 reinoud
824 1.1 reinoud piece = calloc(1, piece_alloc_len);
825 1.1 reinoud if (piece == NULL)
826 1.1 reinoud return errno;
827 1.1 reinoud if (ad_type == UDF_ICB_INTERN_ALLOC) {
828 1.1 reinoud memcpy(piece, bpos, piece_len);
829 1.1 reinoud } else if (flags == 0) {
830 1.1 reinoud /* not empty */
831 1.1 reinoud /* read sector by sector reading as much as possible */
832 1.1 reinoud for (i = 0; i < piece_sectors; i++) {
833 1.1 reinoud piece_error = udf_read_virt(
834 1.1 reinoud piece + i * context.sector_size,
835 1.1 reinoud lb_num + i, vpart_num, 1);
836 1.1 reinoud if (piece_error)
837 1.1 reinoud return_error = piece_error;
838 1.1 reinoud }
839 1.1 reinoud }
840 1.1 reinoud
841 1.1 reinoud alloc_len = UDF_ROUNDUP(fpos + piece_len, context.sector_size);
842 1.1 reinoud error = reallocarr(resultp, 1, alloc_len);
843 1.1 reinoud if (error) {
844 1.1 reinoud /* fatal */
845 1.1 reinoud free(piece);
846 1.1 reinoud free(*resultp);
847 1.1 reinoud return errno;
848 1.1 reinoud }
849 1.1 reinoud
850 1.1 reinoud memcpy(*resultp + fpos, piece, piece_alloc_len);
851 1.1 reinoud free(piece);
852 1.1 reinoud }
853 1.1 reinoud if (action & AD_ADJUST_FIDS) {
854 1.1 reinoud piece = *resultp + fpos;
855 1.1 reinoud if (ad_type == UDF_ICB_INTERN_ALLOC) {
856 1.1 reinoud udf_fids_fixup(piece, piece_len, process_context,
857 1.1 reinoud dscr_lb_num);
858 1.1 reinoud } else if (flags == 0) {
859 1.1 reinoud udf_fids_fixup(piece, piece_len, process_context,
860 1.1 reinoud lb_num);
861 1.1 reinoud }
862 1.1 reinoud }
863 1.1 reinoud if (action & AD_CHECK_FIDS) {
864 1.1 reinoud piece = *resultp + fpos;
865 1.1 reinoud if (ad_type == UDF_ICB_INTERN_ALLOC) {
866 1.1 reinoud error = udf_quick_check_fids_piece(piece, piece_len,
867 1.1 reinoud process_context, dscr_lb_num);
868 1.1 reinoud } else if (flags == 0) {
869 1.1 reinoud error = udf_quick_check_fids_piece(piece, piece_len,
870 1.1 reinoud process_context, lb_num);
871 1.1 reinoud }
872 1.1 reinoud if (error)
873 1.1 reinoud return error;
874 1.1 reinoud }
875 1.1 reinoud if (action & AD_SAVE_FILE) {
876 1.1 reinoud /*
877 1.1 reinoud * Note: only used for directory contents.
878 1.1 reinoud */
879 1.1 reinoud piece = *resultp + fpos;
880 1.1 reinoud if (ad_type == UDF_ICB_INTERN_ALLOC) {
881 1.1 reinoud memcpy(bpos, piece, piece_len);
882 1.1 reinoud /* nothing */
883 1.1 reinoud } else if (flags == 0) {
884 1.1 reinoud /* not empty */
885 1.1 reinoud error = udf_write_virt(
886 1.1 reinoud piece, lb_num, vpart_num,
887 1.1 reinoud piece_sectors);
888 1.1 reinoud if (error) {
889 1.1 reinoud pwarn("Got error writing piece\n");
890 1.1 reinoud return error;
891 1.1 reinoud }
892 1.1 reinoud } else {
893 1.1 reinoud /* allocated but not written piece, skip */
894 1.1 reinoud }
895 1.1 reinoud }
896 1.1 reinoud if (action & AD_CHECK_USED) {
897 1.1 reinoud if (ad_type == UDF_ICB_INTERN_ALLOC) {
898 1.1 reinoud /* nothing */
899 1.1 reinoud } else if (flags != UDF_EXT_FREE) {
900 1.1 reinoud struct udf_fsck_node *node = process_context;
901 1.1 reinoud (void) udf_check_if_allocated(
902 1.1 reinoud node,
903 1.1 reinoud FSCK_OVERLAP_EXTENT,
904 1.1 reinoud lb_num, vpart_num,
905 1.1 reinoud piece_len);
906 1.1 reinoud }
907 1.1 reinoud }
908 1.1 reinoud if (action & AD_FIND_OVERLAP_PAIR) {
909 1.1 reinoud if (ad_type == UDF_ICB_INTERN_ALLOC) {
910 1.1 reinoud /* nothing */
911 1.1 reinoud } else if (flags != UDF_EXT_FREE) {
912 1.1 reinoud struct udf_fsck_node *node = process_context;
913 1.1 reinoud udf_check_overlap_pair(
914 1.1 reinoud node,
915 1.1 reinoud FSCK_OVERLAP_EXTENT,
916 1.1 reinoud lb_num, vpart_num,
917 1.1 reinoud piece_len);
918 1.1 reinoud }
919 1.1 reinoud }
920 1.1 reinoud if (action & AD_MARK_AS_USED) {
921 1.1 reinoud if (ad_type == UDF_ICB_INTERN_ALLOC) {
922 1.1 reinoud /* nothing */
923 1.1 reinoud } else if (flags != UDF_EXT_FREE) {
924 1.1 reinoud udf_mark_allocated(lb_num, vpart_num,
925 1.1 reinoud udf_bytes_to_sectors(piece_len));
926 1.1 reinoud }
927 1.1 reinoud }
928 1.1 reinoud
929 1.1 reinoud return return_error;
930 1.1 reinoud }
931 1.1 reinoud
932 1.1 reinoud
933 1.1 reinoud static int
934 1.1 reinoud udf_process_file(union dscrptr *dscrptr, int vpart_num, uint8_t **resultp,
935 1.1 reinoud int action, void *process_context)
936 1.1 reinoud {
937 1.1 reinoud struct file_entry *fe = &dscrptr->fe;
938 1.1 reinoud struct extfile_entry *efe = &dscrptr->efe;
939 1.1 reinoud struct desc_tag *tag = &dscrptr->tag;
940 1.1 reinoud struct alloc_ext_entry *ext;
941 1.1 reinoud struct icb_tag *icb;
942 1.1 reinoud struct long_ad *long_adp = NULL;
943 1.1 reinoud struct short_ad *short_adp = NULL;
944 1.1 reinoud union dscrptr *extdscr = NULL;
945 1.1 reinoud uint64_t fpos;
946 1.1 reinoud uint32_t l_ad, l_ea, piece_len, lb_num, flags;
947 1.1 reinoud uint8_t *bpos;
948 1.1 reinoud int id, extid, ad_type, ad_len;
949 1.1 reinoud int error;
950 1.1 reinoud
951 1.1 reinoud id = udf_rw16(tag->id);
952 1.1 reinoud assert(id == TAGID_FENTRY || id == TAGID_EXTFENTRY);
953 1.1 reinoud
954 1.1 reinoud if (action & AD_CHECK_USED) {
955 1.1 reinoud struct udf_fsck_node *node = process_context;
956 1.1 reinoud (void) udf_check_if_allocated(
957 1.1 reinoud node,
958 1.1 reinoud FSCK_OVERLAP_MAIN_NODE,
959 1.1 reinoud udf_rw32(node->loc.loc.lb_num),
960 1.1 reinoud udf_rw16(node->loc.loc.part_num),
961 1.1 reinoud context.sector_size);
962 1.1 reinoud /* return error code? */
963 1.1 reinoud }
964 1.1 reinoud
965 1.1 reinoud if (action & AD_FIND_OVERLAP_PAIR) {
966 1.1 reinoud struct udf_fsck_node *node = process_context;
967 1.1 reinoud udf_check_overlap_pair(
968 1.1 reinoud node,
969 1.1 reinoud FSCK_OVERLAP_MAIN_NODE,
970 1.1 reinoud udf_rw32(node->loc.loc.lb_num),
971 1.1 reinoud udf_rw16(node->loc.loc.part_num),
972 1.1 reinoud context.sector_size);
973 1.1 reinoud /* return error code? */
974 1.1 reinoud }
975 1.1 reinoud
976 1.1 reinoud if (action & AD_MARK_AS_USED)
977 1.1 reinoud udf_mark_allocated(udf_rw32(tag->tag_loc), vpart_num, 1);
978 1.1 reinoud
979 1.1 reinoud if (id == TAGID_FENTRY) {
980 1.1 reinoud icb = &fe->icbtag;
981 1.1 reinoud l_ad = udf_rw32(fe->l_ad);
982 1.1 reinoud l_ea = udf_rw32(fe->l_ea);
983 1.1 reinoud bpos = (uint8_t *) fe->data + l_ea;
984 1.1 reinoud } else {
985 1.1 reinoud icb = &efe->icbtag;
986 1.1 reinoud l_ad = udf_rw32(efe->l_ad);
987 1.1 reinoud l_ea = udf_rw32(efe->l_ea);
988 1.1 reinoud bpos = (uint8_t *) efe->data + l_ea;
989 1.1 reinoud }
990 1.1 reinoud
991 1.1 reinoud ad_type = udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
992 1.1 reinoud if (ad_type == UDF_ICB_INTERN_ALLOC) {
993 1.1 reinoud error = udf_process_ad(dscrptr, action, resultp, -1, 0,
994 1.1 reinoud NULL, NULL, process_context);
995 1.1 reinoud return error;
996 1.1 reinoud }
997 1.1 reinoud if ((ad_type != UDF_ICB_SHORT_ALLOC) &&
998 1.1 reinoud (ad_type != UDF_ICB_LONG_ALLOC))
999 1.1 reinoud return EINVAL;
1000 1.1 reinoud
1001 1.1 reinoud if (ad_type == UDF_ICB_SHORT_ALLOC)
1002 1.1 reinoud short_adp = (struct short_ad *) bpos;
1003 1.1 reinoud else
1004 1.1 reinoud long_adp = (struct long_ad *) bpos;
1005 1.1 reinoud ;
1006 1.1 reinoud
1007 1.1 reinoud if (action & AD_SAVE_FILE) {
1008 1.1 reinoud /*
1009 1.1 reinoud * Special case for writeout file/directory on recordable
1010 1.1 reinoud * media. We write in one go so wipe and (re)allocate the
1011 1.1 reinoud * entire space.
1012 1.1 reinoud */
1013 1.1 reinoud if (context.format_flags & FORMAT_VAT)
1014 1.1 reinoud udf_wipe_and_reallocate(dscrptr, vpart_num, &l_ad);
1015 1.1 reinoud }
1016 1.1 reinoud
1017 1.1 reinoud fpos = 0;
1018 1.1 reinoud bpos = NULL;
1019 1.1 reinoud error = 0;
1020 1.1 reinoud while (l_ad) {
1021 1.1 reinoud if (ad_type == UDF_ICB_SHORT_ALLOC) {
1022 1.1 reinoud piece_len = udf_rw32(short_adp->len);
1023 1.1 reinoud lb_num = udf_rw32(short_adp->lb_num);
1024 1.1 reinoud ad_len = sizeof(struct short_ad);
1025 1.1 reinoud } else /* UDF_ICB_LONG_ALLOC */ {
1026 1.1 reinoud piece_len = udf_rw32(long_adp->len);
1027 1.1 reinoud lb_num = udf_rw32(long_adp->loc.lb_num);
1028 1.1 reinoud vpart_num = udf_rw16(long_adp->loc.part_num);
1029 1.1 reinoud ad_len = sizeof(struct long_ad);
1030 1.1 reinoud }
1031 1.1 reinoud flags = UDF_EXT_FLAGS(piece_len);
1032 1.1 reinoud piece_len = UDF_EXT_LEN(piece_len);
1033 1.1 reinoud
1034 1.1 reinoud switch (flags) {
1035 1.1 reinoud default :
1036 1.1 reinoud error = udf_process_ad(dscrptr, action, resultp,
1037 1.1 reinoud vpart_num, fpos, short_adp, long_adp,
1038 1.1 reinoud process_context);
1039 1.1 reinoud break;
1040 1.1 reinoud case UDF_EXT_REDIRECT :
1041 1.1 reinoud if (piece_len != context.sector_size) {
1042 1.1 reinoud /* should this be an error? */
1043 1.2 wiz pwarn("Got extension redirect with wrong size %d\n",
1044 1.1 reinoud piece_len);
1045 1.1 reinoud error = EINVAL;
1046 1.1 reinoud break;
1047 1.1 reinoud }
1048 1.1 reinoud free(extdscr);
1049 1.1 reinoud error = udf_read_dscr_virt(lb_num, vpart_num, &extdscr);
1050 1.1 reinoud if (error)
1051 1.1 reinoud break;
1052 1.1 reinoud /* empty block is terminator */
1053 1.1 reinoud if (extdscr == NULL)
1054 1.1 reinoud return 0;
1055 1.1 reinoud ext = &extdscr->aee;
1056 1.1 reinoud extid = udf_rw16(ext->tag.id);
1057 1.1 reinoud if (extid != TAGID_ALLOCEXTENT) {
1058 1.1 reinoud pwarn("Corruption in allocated extents chain\n");
1059 1.1 reinoud /* corruption! */
1060 1.1 reinoud free(extdscr);
1061 1.1 reinoud errno = EINVAL;
1062 1.1 reinoud break;
1063 1.1 reinoud }
1064 1.1 reinoud
1065 1.1 reinoud if (action & AD_CHECK_USED) {
1066 1.1 reinoud (void) udf_check_if_allocated(
1067 1.1 reinoud (struct udf_fsck_node *) process_context,
1068 1.1 reinoud FSCK_OVERLAP_EXTALLOC,
1069 1.1 reinoud lb_num,
1070 1.1 reinoud vpart_num,
1071 1.1 reinoud context.sector_size);
1072 1.1 reinoud /* returning error code ? */
1073 1.1 reinoud }
1074 1.1 reinoud
1075 1.1 reinoud if (action & AD_FIND_OVERLAP_PAIR) {
1076 1.1 reinoud struct udf_fsck_node *node = process_context;
1077 1.1 reinoud udf_check_overlap_pair(
1078 1.1 reinoud node,
1079 1.1 reinoud FSCK_OVERLAP_EXTALLOC,
1080 1.1 reinoud lb_num,
1081 1.1 reinoud vpart_num,
1082 1.1 reinoud context.sector_size);
1083 1.1 reinoud /* return error code? */
1084 1.1 reinoud }
1085 1.1 reinoud
1086 1.1 reinoud if (action & AD_MARK_AS_USED)
1087 1.1 reinoud udf_mark_allocated(
1088 1.1 reinoud lb_num, vpart_num,
1089 1.1 reinoud 1);
1090 1.1 reinoud /* TODO check for prev_entry? */
1091 1.11 reinoud l_ad = udf_rw32(ext->l_ad);
1092 1.1 reinoud bpos = ext->data;
1093 1.1 reinoud if (ad_type == UDF_ICB_SHORT_ALLOC)
1094 1.1 reinoud short_adp = (struct short_ad *) bpos;
1095 1.1 reinoud else
1096 1.1 reinoud long_adp = (struct long_ad *) bpos;
1097 1.1 reinoud ;
1098 1.1 reinoud continue;
1099 1.1 reinoud }
1100 1.1 reinoud if (error)
1101 1.1 reinoud break;
1102 1.1 reinoud
1103 1.1 reinoud if (long_adp) long_adp++;
1104 1.1 reinoud if (short_adp) short_adp++;
1105 1.1 reinoud fpos += piece_len;
1106 1.1 reinoud bpos += piece_len;
1107 1.1 reinoud l_ad -= ad_len;
1108 1.1 reinoud }
1109 1.1 reinoud
1110 1.1 reinoud return error;
1111 1.1 reinoud }
1112 1.1 reinoud
1113 1.1 reinoud
1114 1.1 reinoud static int
1115 1.1 reinoud udf_readin_file(union dscrptr *dscrptr, int vpart_num, uint8_t **resultp,
1116 1.1 reinoud struct udf_fsck_file_stats *statsp)
1117 1.1 reinoud {
1118 1.1 reinoud struct udf_fsck_file_stats stats;
1119 1.1 reinoud int error;
1120 1.1 reinoud
1121 1.1 reinoud bzero(&stats, sizeof(stats));
1122 1.1 reinoud *resultp = NULL;
1123 1.1 reinoud error = udf_process_file(dscrptr, vpart_num, resultp,
1124 1.1 reinoud AD_LOAD_FILE | AD_GATHER_STATS, (void *) &stats);
1125 1.1 reinoud if (statsp)
1126 1.1 reinoud *statsp = stats;
1127 1.1 reinoud return error;
1128 1.1 reinoud }
1129 1.1 reinoud
1130 1.1 reinoud /* --------------------------------------------------------------------- */
1131 1.1 reinoud
1132 1.1 reinoud #define MAX_BSIZE (0x10000)
1133 1.1 reinoud #define UDF_ISO_VRS_SIZE (32*2048) /* 32 ISO `sectors' */
1134 1.1 reinoud
1135 1.1 reinoud static void
1136 1.1 reinoud udf_check_vrs9660(void)
1137 1.1 reinoud {
1138 1.1 reinoud struct vrs_desc *vrs;
1139 1.1 reinoud uint8_t buffer[MAX_BSIZE];
1140 1.1 reinoud uint64_t rpos;
1141 1.1 reinoud uint8_t *pos;
1142 1.1 reinoud int max_sectors, sector, factor;
1143 1.1 reinoud int ret, ok;
1144 1.1 reinoud
1145 1.1 reinoud if (context.format_flags & FORMAT_TRACK512)
1146 1.1 reinoud return;
1147 1.1 reinoud
1148 1.1 reinoud /*
1149 1.1 reinoud * location of iso9660 VRS is defined as first sector AFTER 32kb,
1150 1.1 reinoud * minimum `sector size' 2048
1151 1.1 reinoud */
1152 1.1 reinoud layout.iso9660_vrs = ((32*1024 + context.sector_size - 1) /
1153 1.1 reinoud context.sector_size);
1154 1.1 reinoud max_sectors = UDF_ISO_VRS_SIZE / 2048;
1155 1.1 reinoud factor = (2048 + context.sector_size -1) / context.sector_size;
1156 1.1 reinoud
1157 1.1 reinoud ok = 1;
1158 1.1 reinoud rpos = (uint64_t) layout.iso9660_vrs * context.sector_size;
1159 1.1 reinoud ret = pread(dev_fd, buffer, UDF_ISO_VRS_SIZE, rpos);
1160 1.1 reinoud if (ret == -1) {
1161 1.1 reinoud pwarn("Error reading in ISO9660 VRS\n");
1162 1.1 reinoud ok = 0;
1163 1.1 reinoud }
1164 1.1 reinoud if (ok && ((uint32_t) ret != UDF_ISO_VRS_SIZE)) {
1165 1.1 reinoud pwarn("Short read in ISO9660 VRS\n");
1166 1.1 reinoud ok = 0;
1167 1.1 reinoud }
1168 1.1 reinoud
1169 1.1 reinoud if (ok) {
1170 1.1 reinoud ok = 0;
1171 1.1 reinoud for (sector = 0; sector < max_sectors; sector++) {
1172 1.1 reinoud pos = buffer + sector * factor * context.sector_size;
1173 1.1 reinoud vrs = (struct vrs_desc *) pos;
1174 1.1 reinoud if (strncmp((const char *) vrs->identifier, VRS_BEA01, 5) == 0)
1175 1.1 reinoud ok = 1;
1176 1.1 reinoud if (strncmp((const char *) vrs->identifier, VRS_NSR02, 5) == 0)
1177 1.1 reinoud ok |= 2;
1178 1.1 reinoud if (strncmp((const char *) vrs->identifier, VRS_NSR03, 5) == 0)
1179 1.1 reinoud ok |= 2;
1180 1.1 reinoud if (strncmp((const char *) vrs->identifier, VRS_TEA01, 5) == 0) {
1181 1.1 reinoud ok |= 4;
1182 1.1 reinoud break;
1183 1.1 reinoud }
1184 1.1 reinoud }
1185 1.1 reinoud if (ok != 7)
1186 1.1 reinoud ok = 0;
1187 1.1 reinoud }
1188 1.1 reinoud if (!ok) {
1189 1.1 reinoud pwarn("Error in ISO 9660 volume recognition sequence\n");
1190 1.1 reinoud if (context.format_flags & FORMAT_SEQUENTIAL) {
1191 1.1 reinoud pwarn("ISO 9660 volume recognition sequence can't be repaired "
1192 1.1 reinoud "on SEQUENTIAL media\n");
1193 1.1 reinoud } else if (ask(0, "fix ISO 9660 volume recognition sequence")) {
1194 1.1 reinoud if (!rdonly)
1195 1.1 reinoud udf_write_iso9660_vrs();
1196 1.1 reinoud }
1197 1.1 reinoud }
1198 1.1 reinoud }
1199 1.1 reinoud
1200 1.1 reinoud
1201 1.1 reinoud /*
1202 1.1 reinoud * Read in disc and try to find basic properties like sector size, expected
1203 1.1 reinoud * UDF versions etc.
1204 1.1 reinoud */
1205 1.1 reinoud
1206 1.1 reinoud static int
1207 1.1 reinoud udf_find_anchor(int anum)
1208 1.1 reinoud {
1209 1.1 reinoud uint8_t buffer[MAX_BSIZE];
1210 1.1 reinoud struct anchor_vdp *avdp = (struct anchor_vdp *) buffer;
1211 1.1 reinoud uint64_t rpos;
1212 1.1 reinoud uint32_t location;
1213 1.1 reinoud int sz_guess, ret;
1214 1.1 reinoud int error;
1215 1.1 reinoud
1216 1.1 reinoud location = layout.anchors[anum];
1217 1.1 reinoud
1218 1.1 reinoud /*
1219 1.1 reinoud * Search ADVP by reading bigger and bigger sectors NOTE we can't use
1220 1.1 reinoud * udf_read_phys yet since the sector size is not known yet
1221 1.1 reinoud */
1222 1.1 reinoud sz_guess = mmc_discinfo.sector_size; /* assume media is bigger */
1223 1.1 reinoud for (; sz_guess <= MAX_BSIZE; sz_guess += 512) {
1224 1.1 reinoud rpos = (uint64_t) location * sz_guess;
1225 1.1 reinoud ret = pread(dev_fd, buffer, sz_guess, rpos);
1226 1.1 reinoud if (ret == -1) {
1227 1.1 reinoud if (errno == ENODEV)
1228 1.1 reinoud return errno;
1229 1.1 reinoud } else if (ret != sz_guess) {
1230 1.1 reinoud /* most likely EOF, ignore */
1231 1.1 reinoud } else {
1232 1.1 reinoud error = udf_check_tag_and_location(buffer, location);
1233 1.1 reinoud if (!error) {
1234 1.1 reinoud if (udf_rw16(avdp->tag.id) != TAGID_ANCHOR)
1235 1.1 reinoud continue;
1236 1.1 reinoud error = udf_check_tag_payload(buffer, sz_guess);
1237 1.1 reinoud if (!error)
1238 1.1 reinoud break;
1239 1.1 reinoud }
1240 1.1 reinoud }
1241 1.1 reinoud }
1242 1.1 reinoud if (sz_guess > MAX_BSIZE)
1243 1.1 reinoud return -1;
1244 1.1 reinoud
1245 1.1 reinoud /* special case for disc images */
1246 1.1 reinoud if (mmc_discinfo.sector_size != (unsigned int) sz_guess) {
1247 1.1 reinoud emul_sectorsize = sz_guess;
1248 1.1 reinoud udf_update_discinfo();
1249 1.1 reinoud }
1250 1.1 reinoud context.sector_size = sz_guess;
1251 1.1 reinoud context.dscrver = udf_rw16(avdp->tag.descriptor_ver);
1252 1.1 reinoud
1253 1.1 reinoud context.anchors[anum] = calloc(1, context.sector_size);
1254 1.1 reinoud memcpy(context.anchors[anum], avdp, context.sector_size);
1255 1.1 reinoud
1256 1.1 reinoud context.min_udf = 0x102;
1257 1.1 reinoud context.max_udf = 0x150;
1258 1.1 reinoud if (context.dscrver > 2) {
1259 1.1 reinoud context.min_udf = 0x200;
1260 1.1 reinoud context.max_udf = 0x260;
1261 1.1 reinoud }
1262 1.1 reinoud return 0;
1263 1.1 reinoud }
1264 1.1 reinoud
1265 1.1 reinoud
1266 1.1 reinoud static int
1267 1.1 reinoud udf_get_anchors(void)
1268 1.1 reinoud {
1269 1.1 reinoud struct mmc_trackinfo ti;
1270 1.1 reinoud struct anchor_vdp *avdp;
1271 1.1 reinoud int need_fixup, error;
1272 1.1 reinoud
1273 1.1 reinoud memset(&layout, 0, sizeof(layout));
1274 1.1 reinoud memset(&ti, 0, sizeof(ti));
1275 1.1 reinoud
1276 1.1 reinoud /* search start */
1277 1.1 reinoud for (int i = 1; i <= mmc_discinfo.num_tracks; i++) {
1278 1.1 reinoud ti.tracknr = i;
1279 1.1 reinoud error = udf_update_trackinfo(&ti);
1280 1.1 reinoud assert(!error);
1281 1.1 reinoud if (ti.sessionnr == target_session)
1282 1.1 reinoud break;
1283 1.1 reinoud }
1284 1.1 reinoud /* support for track 512 */
1285 1.6 riastrad if (ti.flags & MMC_TRACKINFO_BLANK)
1286 1.1 reinoud context.format_flags |= FORMAT_TRACK512;
1287 1.1 reinoud
1288 1.1 reinoud assert(!error);
1289 1.1 reinoud context.first_ti = ti;
1290 1.1 reinoud
1291 1.1 reinoud /* search end */
1292 1.1 reinoud for (int i = mmc_discinfo.num_tracks; i > 0; i--) {
1293 1.1 reinoud ti.tracknr = i;
1294 1.1 reinoud error = udf_update_trackinfo(&ti);
1295 1.1 reinoud assert(!error);
1296 1.1 reinoud if (ti.sessionnr == target_session)
1297 1.1 reinoud break;
1298 1.1 reinoud }
1299 1.1 reinoud context.last_ti = ti;
1300 1.1 reinoud
1301 1.1 reinoud layout.first_lba = context.first_ti.track_start;
1302 1.1 reinoud layout.last_lba = mmc_discinfo.last_possible_lba;
1303 1.1 reinoud layout.blockingnr = udf_get_blockingnr(&ti);
1304 1.1 reinoud
1305 1.1 reinoud layout.anchors[0] = layout.first_lba + 256;
1306 1.1 reinoud if (context.format_flags & FORMAT_TRACK512)
1307 1.1 reinoud layout.anchors[0] = layout.first_lba + 512;
1308 1.1 reinoud layout.anchors[1] = layout.last_lba - 256;
1309 1.1 reinoud layout.anchors[2] = layout.last_lba;
1310 1.1 reinoud
1311 1.1 reinoud need_fixup = 0;
1312 1.1 reinoud error = udf_find_anchor(0);
1313 1.1 reinoud if (error == ENODEV) {
1314 1.1 reinoud pwarn("Drive empty?\n");
1315 1.1 reinoud return errno;
1316 1.1 reinoud }
1317 1.1 reinoud if (error) {
1318 1.1 reinoud need_fixup = 1;
1319 1.1 reinoud if (!preen)
1320 1.1 reinoud pwarn("Anchor ADVP0 can't be found! Searching others\n");
1321 1.1 reinoud error = udf_find_anchor(2);
1322 1.1 reinoud if (error) {
1323 1.1 reinoud if (!preen)
1324 1.1 reinoud pwarn("Anchor ADVP2 can't be found! Searching ADVP1\n");
1325 1.1 reinoud /* this may be fidly, but search */
1326 1.1 reinoud error = udf_find_anchor(1);
1327 1.1 reinoud if (error) {
1328 1.1 reinoud if (!preen)
1329 1.1 reinoud pwarn("No valid anchors found!\n");
1330 1.1 reinoud /* TODO scan media for VDS? */
1331 1.1 reinoud return -1;
1332 1.1 reinoud }
1333 1.1 reinoud }
1334 1.1 reinoud }
1335 1.1 reinoud
1336 1.1 reinoud if (need_fixup) {
1337 1.1 reinoud if (context.format_flags & FORMAT_SEQUENTIAL) {
1338 1.1 reinoud pwarn("Missing primary anchor can't be resolved on "
1339 1.1 reinoud "SEQUENTIAL media\n");
1340 1.1 reinoud } else if (ask(1, "Fixup missing anchors")) {
1341 1.1 reinoud pwarn("TODO fixup missing anchors\n");
1342 1.1 reinoud need_fixup = 0;
1343 1.1 reinoud }
1344 1.1 reinoud if (need_fixup)
1345 1.1 reinoud return -1;
1346 1.1 reinoud }
1347 1.1 reinoud if (!preen)
1348 1.1 reinoud printf("Filesystem sectorsize is %d bytes.\n\n",
1349 1.1 reinoud context.sector_size);
1350 1.1 reinoud
1351 1.1 reinoud /* update our last track info since our idea of sector size might have changed */
1352 1.1 reinoud (void) udf_update_trackinfo(&context.last_ti);
1353 1.1 reinoud
1354 1.1 reinoud /* sector size is now known */
1355 1.1 reinoud wrtrack_skew = context.last_ti.next_writable % layout.blockingnr;
1356 1.1 reinoud
1357 1.1 reinoud avdp = context.anchors[0];
1358 1.1 reinoud /* extract info from current anchor */
1359 1.1 reinoud layout.vds1 = udf_rw32(avdp->main_vds_ex.loc);
1360 1.1 reinoud layout.vds1_size = udf_rw32(avdp->main_vds_ex.len) / context.sector_size;
1361 1.1 reinoud layout.vds2 = udf_rw32(avdp->reserve_vds_ex.loc);
1362 1.1 reinoud layout.vds2_size = udf_rw32(avdp->reserve_vds_ex.len) / context.sector_size;
1363 1.1 reinoud
1364 1.1 reinoud return 0;
1365 1.1 reinoud }
1366 1.1 reinoud
1367 1.1 reinoud
1368 1.1 reinoud #define UDF_LVINT_HIST_CHUNK 32
1369 1.1 reinoud static void
1370 1.1 reinoud udf_retrieve_lvint(void) {
1371 1.1 reinoud union dscrptr *dscr;
1372 1.1 reinoud struct logvol_int_desc *lvint;
1373 1.1 reinoud struct udf_lvintq *trace;
1374 1.1 reinoud uint32_t lbnum, len, *pos;
1375 1.1 reinoud uint8_t *wpos;
1376 1.1 reinoud int num_partmappings;
1377 1.1 reinoud int error, cnt, trace_len;
1378 1.1 reinoud int sector_size = context.sector_size;
1379 1.1 reinoud
1380 1.1 reinoud len = udf_rw32(context.logical_vol->integrity_seq_loc.len);
1381 1.1 reinoud lbnum = udf_rw32(context.logical_vol->integrity_seq_loc.loc);
1382 1.1 reinoud layout.lvis = lbnum;
1383 1.1 reinoud layout.lvis_size = len / sector_size;
1384 1.1 reinoud
1385 1.1 reinoud udf_create_lvintd(UDF_INTEGRITY_OPEN);
1386 1.1 reinoud
1387 1.1 reinoud /* clean trace and history */
1388 1.1 reinoud memset(context.lvint_trace, 0,
1389 1.1 reinoud UDF_LVDINT_SEGMENTS * sizeof(struct udf_lvintq));
1390 1.1 reinoud context.lvint_history_wpos = 0;
1391 1.1 reinoud context.lvint_history_len = UDF_LVINT_HIST_CHUNK;
1392 1.1 reinoud context.lvint_history = calloc(UDF_LVINT_HIST_CHUNK, sector_size);
1393 1.1 reinoud
1394 1.1 reinoud /* record the length on this segment */
1395 1.1 reinoud context.lvint_history_ondisc_len = (len / sector_size);
1396 1.1 reinoud
1397 1.1 reinoud trace_len = 0;
1398 1.1 reinoud trace = context.lvint_trace;
1399 1.1 reinoud trace->start = lbnum;
1400 1.1 reinoud trace->end = lbnum + len/sector_size;
1401 1.1 reinoud trace->pos = 0;
1402 1.1 reinoud trace->wpos = 0;
1403 1.1 reinoud
1404 1.1 reinoud dscr = NULL;
1405 1.1 reinoud error = 0;
1406 1.1 reinoud while (len) {
1407 1.1 reinoud trace->pos = lbnum - trace->start;
1408 1.1 reinoud trace->wpos = trace->pos + 1;
1409 1.1 reinoud
1410 1.1 reinoud free(dscr);
1411 1.1 reinoud error = udf_read_dscr_phys(lbnum, &dscr);
1412 1.1 reinoud /* bad descriptors mean corruption, terminate */
1413 1.1 reinoud if (error)
1414 1.1 reinoud break;
1415 1.1 reinoud
1416 1.1 reinoud /* empty terminates */
1417 1.1 reinoud if (dscr == NULL) {
1418 1.1 reinoud trace->wpos = trace->pos;
1419 1.1 reinoud break;
1420 1.1 reinoud }
1421 1.1 reinoud
1422 1.1 reinoud /* we got a valid descriptor */
1423 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_TERM) {
1424 1.1 reinoud trace->wpos = trace->pos;
1425 1.1 reinoud break;
1426 1.1 reinoud }
1427 1.1 reinoud /* only logical volume integrity descriptors are valid */
1428 1.1 reinoud if (udf_rw16(dscr->tag.id) != TAGID_LOGVOL_INTEGRITY) {
1429 1.1 reinoud error = ENOENT;
1430 1.1 reinoud break;
1431 1.1 reinoud }
1432 1.1 reinoud lvint = &dscr->lvid;
1433 1.1 reinoud
1434 1.1 reinoud /* see if our history is long enough, with one spare */
1435 1.1 reinoud if (context.lvint_history_wpos+2 >= context.lvint_history_len) {
1436 1.1 reinoud int new_len = context.lvint_history_len +
1437 1.1 reinoud UDF_LVINT_HIST_CHUNK;
1438 1.1 reinoud if (reallocarr(&context.lvint_history,
1439 1.1 reinoud new_len, sector_size))
1440 1.1 reinoud err(FSCK_EXIT_CHECK_FAILED, "can't expand logvol history");
1441 1.1 reinoud context.lvint_history_len = new_len;
1442 1.1 reinoud }
1443 1.1 reinoud
1444 1.1 reinoud /* are we linking to a new piece? */
1445 1.1 reinoud if (lvint->next_extent.len) {
1446 1.1 reinoud len = udf_rw32(lvint->next_extent.len);
1447 1.1 reinoud lbnum = udf_rw32(lvint->next_extent.loc);
1448 1.1 reinoud
1449 1.1 reinoud if (trace_len >= UDF_LVDINT_SEGMENTS-1) {
1450 1.1 reinoud /* IEK! segment link full... */
1451 1.1 reinoud pwarn("implementation limit: logical volume "
1452 1.1 reinoud "integrity segment list full\n");
1453 1.1 reinoud error = ENOMEM;
1454 1.1 reinoud break;
1455 1.1 reinoud }
1456 1.1 reinoud trace++;
1457 1.1 reinoud trace_len++;
1458 1.1 reinoud
1459 1.1 reinoud trace->start = lbnum;
1460 1.1 reinoud trace->end = lbnum + len/sector_size;
1461 1.1 reinoud trace->pos = 0;
1462 1.1 reinoud trace->wpos = 0;
1463 1.1 reinoud
1464 1.1 reinoud context.lvint_history_ondisc_len += (len / sector_size);
1465 1.1 reinoud }
1466 1.1 reinoud
1467 1.1 reinoud /* record this found lvint; it is one sector long */
1468 1.1 reinoud wpos = context.lvint_history +
1469 1.1 reinoud context.lvint_history_wpos * sector_size;
1470 1.1 reinoud memcpy(wpos, dscr, sector_size);
1471 1.1 reinoud memcpy(context.logvol_integrity, dscr, sector_size);
1472 1.1 reinoud context.lvint_history_wpos++;
1473 1.1 reinoud
1474 1.1 reinoud /* proceed sequential */
1475 1.1 reinoud lbnum += 1;
1476 1.1 reinoud len -= sector_size;
1477 1.1 reinoud }
1478 1.1 reinoud
1479 1.1 reinoud /* clean up the mess, esp. when there is an error */
1480 1.1 reinoud free(dscr);
1481 1.1 reinoud
1482 1.1 reinoud if (error) {
1483 1.1 reinoud if (!preen)
1484 1.1 reinoud printf("Error in logical volume integrity sequence\n");
1485 1.1 reinoud printf("Marking logical volume integrity OPEN\n");
1486 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_OPEN);
1487 1.1 reinoud }
1488 1.1 reinoud
1489 1.1 reinoud if (udf_rw16(context.logvol_info->min_udf_readver) > context.min_udf)
1490 1.1 reinoud context.min_udf = udf_rw16(context.logvol_info->min_udf_readver);
1491 1.1 reinoud if (udf_rw16(context.logvol_info->min_udf_writever) > context.min_udf)
1492 1.1 reinoud context.min_udf = udf_rw16(context.logvol_info->min_udf_writever);
1493 1.1 reinoud if (udf_rw16(context.logvol_info->max_udf_writever) < context.max_udf)
1494 1.1 reinoud context.max_udf = udf_rw16(context.logvol_info->max_udf_writever);
1495 1.1 reinoud
1496 1.1 reinoud context.unique_id = udf_rw64(context.logvol_integrity->lvint_next_unique_id);
1497 1.1 reinoud
1498 1.1 reinoud /* fill in current size/free values */
1499 1.1 reinoud pos = &context.logvol_integrity->tables[0];
1500 1.1 reinoud num_partmappings = udf_rw32(context.logical_vol->n_pm);
1501 1.1 reinoud for (cnt = 0; cnt < num_partmappings; cnt++) {
1502 1.1 reinoud context.part_free[cnt] = udf_rw32(*pos);
1503 1.1 reinoud pos++;
1504 1.1 reinoud }
1505 1.1 reinoud /* leave the partition sizes alone; no idea why they are stated here */
1506 1.1 reinoud /* TODO sanity check the free space and partition sizes? */
1507 1.1 reinoud
1508 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */
1509 1.1 reinoud //udf_update_lvintd(UDF_INTEGRITY_OPEN);
1510 1.1 reinoud
1511 1.1 reinoud if (!preen) {
1512 1.1 reinoud int ver;
1513 1.1 reinoud
1514 1.1 reinoud printf("\n");
1515 1.1 reinoud ver = udf_rw16(context.logvol_info->min_udf_readver);
1516 1.1 reinoud printf("Minimum read version v%x.%02x\n", ver/0x100, ver&0xff);
1517 1.1 reinoud ver = udf_rw16(context.logvol_info->min_udf_writever);
1518 1.1 reinoud printf("Minimum write version v%x.%02x\n", ver/0x100, ver&0xff);
1519 1.1 reinoud ver = udf_rw16(context.logvol_info->max_udf_writever);
1520 1.1 reinoud printf("Maximum write version v%x.%02x\n", ver/0x100, ver&0xff);
1521 1.1 reinoud
1522 1.1 reinoud printf("\nLast logical volume integrity state is %s.\n",
1523 1.1 reinoud udf_rw32(context.logvol_integrity->integrity_type) ?
1524 1.1 reinoud "CLOSED" : "OPEN");
1525 1.1 reinoud }
1526 1.1 reinoud }
1527 1.1 reinoud
1528 1.1 reinoud
1529 1.1 reinoud static int
1530 1.1 reinoud udf_writeout_lvint(void)
1531 1.1 reinoud {
1532 1.1 reinoud union dscrptr *terminator;
1533 1.1 reinoud struct udf_lvintq *intq, *nintq;
1534 1.1 reinoud struct logvol_int_desc *lvint;
1535 1.1 reinoud uint32_t location;
1536 1.1 reinoud int wpos, num_avail;
1537 1.1 reinoud int sector_size = context.sector_size;
1538 1.1 reinoud int integrity_type, error;
1539 1.1 reinoud int next_present, end_slot, last_segment;
1540 1.1 reinoud
1541 1.1 reinoud /* only write out when its open */
1542 1.1 reinoud integrity_type = udf_rw32(context.logvol_integrity->integrity_type);
1543 1.1 reinoud if (integrity_type == UDF_INTEGRITY_CLOSED)
1544 1.1 reinoud return 0;
1545 1.1 reinoud
1546 1.1 reinoud if (!preen)
1547 1.1 reinoud printf("\n");
1548 1.1 reinoud if (!ask(1, "Write out modifications"))
1549 1.1 reinoud return 0;
1550 1.1 reinoud
1551 1.1 reinoud udf_allow_writing();
1552 1.1 reinoud
1553 1.1 reinoud /* close logical volume */
1554 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_CLOSED);
1555 1.1 reinoud
1556 1.1 reinoud /* do we need to lose some history? */
1557 1.1 reinoud if ((context.lvint_history_ondisc_len - context.lvint_history_wpos) < 2) {
1558 1.1 reinoud uint8_t *src, *dst;
1559 1.1 reinoud uint32_t size;
1560 1.1 reinoud
1561 1.1 reinoud dst = context.lvint_history;
1562 1.1 reinoud src = dst + sector_size;
1563 1.1 reinoud size = (context.lvint_history_wpos-2) * sector_size;
1564 1.1 reinoud memmove(dst, src, size);
1565 1.1 reinoud context.lvint_history_wpos -= 2;
1566 1.1 reinoud }
1567 1.1 reinoud
1568 1.1 reinoud /* write out complete trace just in case */
1569 1.1 reinoud wpos = 0;
1570 1.1 reinoud location = 0;
1571 1.1 reinoud for (int i = 0; i < UDF_LVDINT_SEGMENTS; i++) {
1572 1.1 reinoud intq = &context.lvint_trace[i];
1573 1.1 reinoud nintq = &context.lvint_trace[i+1];
1574 1.1 reinoud
1575 1.1 reinoud /* end of line? */
1576 1.1 reinoud if (intq->start == intq->end)
1577 1.1 reinoud break;
1578 1.1 reinoud num_avail = intq->end - intq->start;
1579 1.1 reinoud location = intq->start;
1580 1.1 reinoud for (int sector = 0; sector < num_avail; sector++) {
1581 1.1 reinoud lvint = (struct logvol_int_desc *)
1582 1.1 reinoud (context.lvint_history + wpos * sector_size);
1583 1.1 reinoud memset(&lvint->next_extent, 0, sizeof(struct extent_ad));
1584 1.1 reinoud next_present = (wpos != context.lvint_history_wpos);
1585 1.1 reinoud end_slot = (sector == num_avail -1);
1586 1.1 reinoud last_segment = (i == UDF_LVDINT_SEGMENTS-1);
1587 1.1 reinoud if (end_slot && next_present && !last_segment) {
1588 1.1 reinoud /* link to next segment */
1589 1.1 reinoud lvint->next_extent.len = udf_rw32(
1590 1.1 reinoud sector_size * (nintq->end - nintq->start));
1591 1.1 reinoud lvint->next_extent.loc = udf_rw32(nintq->start);
1592 1.1 reinoud }
1593 1.1 reinoud error = udf_write_dscr_phys((union dscrptr *) lvint, location, 1);
1594 1.1 reinoud assert(!error);
1595 1.1 reinoud wpos++;
1596 1.1 reinoud location++;
1597 1.1 reinoud if (wpos == context.lvint_history_wpos)
1598 1.1 reinoud break;
1599 1.1 reinoud }
1600 1.1 reinoud }
1601 1.1 reinoud
1602 1.1 reinoud /* at write pos, write out our integrity */
1603 1.1 reinoud assert(location);
1604 1.1 reinoud lvint = context.logvol_integrity;
1605 1.1 reinoud error = udf_write_dscr_phys((union dscrptr *) lvint, location, 1);
1606 1.1 reinoud assert(!error);
1607 1.1 reinoud wpos++;
1608 1.1 reinoud location++;
1609 1.1 reinoud
1610 1.1 reinoud /* write out terminator */
1611 1.1 reinoud terminator = calloc(1, context.sector_size);
1612 1.1 reinoud assert(terminator);
1613 1.1 reinoud udf_create_terminator(terminator, 0);
1614 1.1 reinoud
1615 1.1 reinoud /* same or increasing serial number: ECMA 3/7.2.5, 4/7.2.5, UDF 2.3.1.1. */
1616 1.1 reinoud terminator->tag.serial_num = lvint->tag.serial_num;
1617 1.1 reinoud
1618 1.1 reinoud error = udf_write_dscr_phys(terminator, location, 1);
1619 1.1 reinoud free(terminator);
1620 1.1 reinoud assert(!error);
1621 1.1 reinoud wpos++;
1622 1.1 reinoud location++;
1623 1.1 reinoud
1624 1.1 reinoud return 0;
1625 1.1 reinoud }
1626 1.1 reinoud
1627 1.1 reinoud
1628 1.1 reinoud static int
1629 1.1 reinoud udf_readin_partitions_free_space(void)
1630 1.1 reinoud {
1631 1.1 reinoud union dscrptr *dscr;
1632 1.1 reinoud struct part_desc *part;
1633 1.1 reinoud struct part_hdr_desc *phd;
1634 1.1 reinoud uint32_t bitmap_len, bitmap_lb;
1635 1.1 reinoud int cnt, tagid, error;
1636 1.1 reinoud
1637 1.1 reinoud /* XXX freed space bitmap ignored XXX */
1638 1.1 reinoud error = 0;
1639 1.1 reinoud for (cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
1640 1.1 reinoud part = context.partitions[cnt];
1641 1.1 reinoud if (!part)
1642 1.1 reinoud continue;
1643 1.1 reinoud
1644 1.1 reinoud phd = &part->pd_part_hdr;
1645 1.1 reinoud bitmap_len = udf_rw32(phd->unalloc_space_bitmap.len);
1646 1.1 reinoud bitmap_lb = udf_rw32(phd->unalloc_space_bitmap.lb_num);
1647 1.1 reinoud
1648 1.1 reinoud if (bitmap_len == 0) {
1649 1.1 reinoud error = 0;
1650 1.1 reinoud continue;
1651 1.1 reinoud }
1652 1.1 reinoud
1653 1.1 reinoud if (!preen)
1654 1.1 reinoud printf("Reading in free space map for partition %d\n", cnt);
1655 1.1 reinoud error = udf_read_dscr_virt(bitmap_lb, cnt, &dscr);
1656 1.1 reinoud if (error)
1657 1.1 reinoud break;
1658 1.1 reinoud if (!dscr) {
1659 1.1 reinoud error = ENOENT;
1660 1.1 reinoud break;
1661 1.1 reinoud }
1662 1.1 reinoud tagid = udf_rw16(dscr->tag.id);
1663 1.1 reinoud if (tagid != TAGID_SPACE_BITMAP) {
1664 1.1 reinoud pwarn("Unallocated space bitmap expected but got "
1665 1.1 reinoud "tag %d\n", tagid);
1666 1.1 reinoud free(dscr);
1667 1.1 reinoud error = ENOENT;
1668 1.1 reinoud break;
1669 1.1 reinoud }
1670 1.1 reinoud if (udf_tagsize(dscr, context.sector_size) > bitmap_len) {
1671 1.1 reinoud pwarn("Warning, size of read in bitmap %d is "
1672 1.1 reinoud "not equal to expected size %d\n",
1673 1.1 reinoud udf_tagsize(dscr, context.sector_size),
1674 1.1 reinoud bitmap_len);
1675 1.1 reinoud }
1676 1.1 reinoud context.part_unalloc_bits[cnt] = &dscr->sbd;
1677 1.1 reinoud }
1678 1.1 reinoud
1679 1.1 reinoud /* special case for metadata partitions */
1680 1.1 reinoud for (cnt = 0; cnt < UDF_PMAPS; cnt++) {
1681 1.1 reinoud if (context.vtop_tp[cnt] != UDF_VTOP_TYPE_META)
1682 1.1 reinoud continue;
1683 1.1 reinoud /* only if present */
1684 1.1 reinoud if (layout.meta_bitmap == 0xffffffff)
1685 1.1 reinoud continue;
1686 1.1 reinoud if (!preen)
1687 1.1 reinoud printf("Reading in free space map for partition %d\n", cnt);
1688 1.1 reinoud error = udf_readin_file(
1689 1.1 reinoud (union dscrptr *) context.meta_bitmap,
1690 1.1 reinoud context.vtop[cnt],
1691 1.1 reinoud (uint8_t **) &context.part_unalloc_bits[cnt],
1692 1.1 reinoud NULL);
1693 1.1 reinoud if (error) {
1694 1.1 reinoud free(context.part_unalloc_bits[cnt]);
1695 1.1 reinoud context.part_unalloc_bits[cnt] = NULL;
1696 1.1 reinoud pwarn("implementation limit: metadata bitmap file read error, "
1697 1.1 reinoud "can't fix this up yet\n");
1698 1.1 reinoud return error;
1699 1.1 reinoud }
1700 1.1 reinoud }
1701 1.1 reinoud if (!preen)
1702 1.1 reinoud printf("\n");
1703 1.1 reinoud
1704 1.1 reinoud return error;
1705 1.1 reinoud }
1706 1.1 reinoud
1707 1.1 reinoud
1708 1.1 reinoud /* ------------------------- VAT support ------------------------- */
1709 1.1 reinoud
1710 1.1 reinoud /*
1711 1.1 reinoud * Update logical volume name in all structures that keep a record of it. We
1712 1.1 reinoud * use memmove since each of them might be specified as a source.
1713 1.1 reinoud *
1714 1.1 reinoud * Note that it doesn't update the VAT structure!
1715 1.1 reinoud */
1716 1.1 reinoud
1717 1.1 reinoud static void
1718 1.1 reinoud udf_update_logvolname(char *logvol_id)
1719 1.1 reinoud {
1720 1.1 reinoud struct logvol_desc *lvd = NULL;
1721 1.1 reinoud struct fileset_desc *fsd = NULL;
1722 1.1 reinoud struct udf_lv_info *lvi = NULL;
1723 1.1 reinoud
1724 1.1 reinoud lvd = context.logical_vol;
1725 1.1 reinoud fsd = context.fileset_desc;
1726 1.1 reinoud if (context.implementation)
1727 1.1 reinoud lvi = &context.implementation->_impl_use.lv_info;
1728 1.1 reinoud
1729 1.1 reinoud /* logvol's id might be specified as original so use memmove here */
1730 1.1 reinoud memmove(lvd->logvol_id, logvol_id, 128);
1731 1.1 reinoud if (fsd)
1732 1.1 reinoud memmove(fsd->logvol_id, logvol_id, 128);
1733 1.1 reinoud if (lvi)
1734 1.1 reinoud memmove(lvi->logvol_id, logvol_id, 128);
1735 1.1 reinoud }
1736 1.1 reinoud
1737 1.1 reinoud
1738 1.1 reinoud static struct timestamp *
1739 1.1 reinoud udf_file_mtime(union dscrptr *dscr)
1740 1.1 reinoud {
1741 1.1 reinoud int tag_id = udf_rw16(dscr->tag.id);
1742 1.1 reinoud
1743 1.1 reinoud assert((tag_id == TAGID_FENTRY) || (tag_id == TAGID_EXTFENTRY));
1744 1.1 reinoud if (tag_id == TAGID_FENTRY)
1745 1.1 reinoud return &dscr->fe.mtime;
1746 1.6 riastrad else
1747 1.1 reinoud return &dscr->efe.mtime;
1748 1.1 reinoud ;
1749 1.1 reinoud }
1750 1.1 reinoud
1751 1.1 reinoud
1752 1.1 reinoud static void
1753 1.1 reinoud udf_print_vat_details(union dscrptr *dscr)
1754 1.1 reinoud {
1755 1.1 reinoud printf("\n");
1756 1.1 reinoud udf_print_timestamp("\tFound VAT timestamped at ",
1757 1.1 reinoud udf_file_mtime(dscr), "\n");
1758 1.1 reinoud }
1759 1.1 reinoud
1760 1.1 reinoud
1761 1.1 reinoud static int
1762 1.1 reinoud udf_check_for_vat(union dscrptr *dscr)
1763 1.1 reinoud {
1764 1.1 reinoud struct icb_tag *icbtag;
1765 1.1 reinoud uint32_t vat_length;
1766 1.1 reinoud int tag_id, filetype;
1767 1.1 reinoud
1768 1.1 reinoud tag_id = udf_rw16(dscr->tag.id);
1769 1.1 reinoud
1770 1.1 reinoud if ((tag_id != TAGID_FENTRY) && (tag_id != TAGID_EXTFENTRY))
1771 1.1 reinoud return ENOENT;
1772 1.1 reinoud
1773 1.1 reinoud if (tag_id == TAGID_FENTRY) {
1774 1.1 reinoud vat_length = udf_rw64(dscr->fe.inf_len);
1775 1.1 reinoud icbtag = &dscr->fe.icbtag;
1776 1.1 reinoud } else {
1777 1.1 reinoud vat_length = udf_rw64(dscr->efe.inf_len);
1778 1.1 reinoud icbtag = &dscr->efe.icbtag;
1779 1.1 reinoud }
1780 1.1 reinoud filetype = icbtag->file_type;
1781 1.1 reinoud if ((filetype != 0) && (filetype != UDF_ICB_FILETYPE_VAT))
1782 1.1 reinoud return ENOENT;
1783 1.1 reinoud
1784 1.1 reinoud /* TODO sanity check vat length */
1785 1.5 riastrad (void)vat_length;
1786 1.1 reinoud
1787 1.1 reinoud return 0;
1788 1.1 reinoud }
1789 1.1 reinoud
1790 1.1 reinoud
1791 1.1 reinoud static int
1792 1.1 reinoud udf_extract_vat(union dscrptr *dscr, uint8_t **vat_contents)
1793 1.1 reinoud {
1794 1.1 reinoud struct udf_fsck_file_stats stats;
1795 1.1 reinoud struct icb_tag *icbtag;
1796 1.1 reinoud struct timestamp *mtime;
1797 1.1 reinoud struct udf_vat *vat;
1798 1.1 reinoud struct udf_oldvat_tail *oldvat_tl;
1799 1.1 reinoud struct udf_logvol_info *lvinfo;
1800 1.1 reinoud struct impl_extattr_entry *implext;
1801 1.1 reinoud struct vatlvext_extattr_entry lvext;
1802 1.1 reinoud const char *extstr = "*UDF VAT LVExtension";
1803 1.1 reinoud uint64_t vat_unique_id;
1804 1.1 reinoud uint64_t vat_length;
1805 1.1 reinoud uint32_t vat_entries, vat_offset;
1806 1.1 reinoud uint32_t offset, a_l;
1807 1.1 reinoud uint8_t *ea_start, *lvextpos;
1808 1.1 reinoud char *regid_name;
1809 1.1 reinoud int tag_id, filetype;
1810 1.1 reinoud int error;
1811 1.1 reinoud
1812 1.1 reinoud *vat_contents = NULL;
1813 1.1 reinoud lvinfo = context.logvol_info;
1814 1.1 reinoud
1815 1.1 reinoud /* read in VAT contents */
1816 1.1 reinoud error = udf_readin_file(dscr, context.data_part, vat_contents, &stats);
1817 1.1 reinoud if (error) {
1818 1.1 reinoud error = ENOENT;
1819 1.1 reinoud goto out;
1820 1.1 reinoud }
1821 1.1 reinoud
1822 1.1 reinoud /* tag_id already checked */
1823 1.1 reinoud tag_id = udf_rw16(dscr->tag.id);
1824 1.1 reinoud if (tag_id == TAGID_FENTRY) {
1825 1.1 reinoud vat_length = udf_rw64(dscr->fe.inf_len);
1826 1.1 reinoud icbtag = &dscr->fe.icbtag;
1827 1.1 reinoud mtime = &dscr->fe.mtime;
1828 1.1 reinoud vat_unique_id = udf_rw64(dscr->fe.unique_id);
1829 1.1 reinoud ea_start = dscr->fe.data;
1830 1.1 reinoud } else {
1831 1.1 reinoud vat_length = udf_rw64(dscr->efe.inf_len);
1832 1.1 reinoud icbtag = &dscr->efe.icbtag;
1833 1.1 reinoud mtime = &dscr->efe.mtime;
1834 1.1 reinoud vat_unique_id = udf_rw64(dscr->efe.unique_id);
1835 1.1 reinoud ea_start = dscr->efe.data; /* for completion */
1836 1.1 reinoud }
1837 1.1 reinoud
1838 1.1 reinoud if (vat_length > stats.inf_len) {
1839 1.1 reinoud error = ENOENT;
1840 1.1 reinoud goto out;
1841 1.1 reinoud }
1842 1.1 reinoud
1843 1.1 reinoud /* file type already checked */
1844 1.1 reinoud filetype = icbtag->file_type;
1845 1.1 reinoud
1846 1.1 reinoud /* extract info from our VAT data */
1847 1.1 reinoud if (filetype == 0) {
1848 1.1 reinoud /* VAT 1.50 format */
1849 1.1 reinoud /* definition */
1850 1.1 reinoud vat_offset = 0;
1851 1.1 reinoud vat_entries = (vat_length-36)/4;
1852 1.1 reinoud oldvat_tl = (struct udf_oldvat_tail *)
1853 1.1 reinoud (*vat_contents + vat_entries * 4);
1854 1.1 reinoud regid_name = (char *) oldvat_tl->id.id;
1855 1.1 reinoud error = strncmp(regid_name, "*UDF Virtual Alloc Tbl", 22);
1856 1.1 reinoud if (error) {
1857 1.1 reinoud pwarn("Possible VAT 1.50 detected without tail\n");
1858 1.1 reinoud if (ask_noauto(0, "Accept anyway")) {
1859 1.1 reinoud vat_entries = vat_length/4;
1860 1.1 reinoud vat_writeout = 1;
1861 1.1 reinoud error = 0;
1862 1.1 reinoud goto ok;
1863 1.1 reinoud }
1864 1.1 reinoud pwarn("VAT format 1.50 rejected\n");
1865 1.1 reinoud error = ENOENT;
1866 1.1 reinoud goto out;
1867 1.1 reinoud }
1868 1.1 reinoud
1869 1.1 reinoud /*
1870 1.1 reinoud * The following VAT extensions are optional and ignored but
1871 1.1 reinoud * demand a clean VAT write out for sanity.
1872 1.1 reinoud */
1873 1.1 reinoud error = udf_extattr_search_intern(dscr, 2048, extstr, &offset, &a_l);
1874 1.1 reinoud if (error) {
1875 1.1 reinoud /* VAT LVExtension extended attribute missing */
1876 1.10 reinoud error = 0;
1877 1.1 reinoud vat_writeout = 1;
1878 1.1 reinoud goto ok;
1879 1.1 reinoud }
1880 1.1 reinoud
1881 1.1 reinoud implext = (struct impl_extattr_entry *) (ea_start + offset);
1882 1.1 reinoud error = udf_impl_extattr_check(implext);
1883 1.1 reinoud if (error) {
1884 1.1 reinoud /* VAT LVExtension checksum failed */
1885 1.10 reinoud error = 0;
1886 1.1 reinoud vat_writeout = 1;
1887 1.1 reinoud goto ok;
1888 1.1 reinoud }
1889 1.1 reinoud
1890 1.1 reinoud /* paranoia */
1891 1.1 reinoud if (a_l != sizeof(*implext) -2 + udf_rw32(implext->iu_l) + sizeof(lvext)) {
1892 1.1 reinoud /* VAT LVExtension size doesn't compute */
1893 1.10 reinoud error = 0;
1894 1.1 reinoud vat_writeout = 1;
1895 1.1 reinoud goto ok;
1896 1.1 reinoud }
1897 1.1 reinoud
1898 1.1 reinoud /*
1899 1.1 reinoud * We have found our "VAT LVExtension attribute. BUT due to a
1900 1.1 reinoud * bug in the specification it might not be word aligned so
1901 1.1 reinoud * copy first to avoid panics on some machines (!!)
1902 1.1 reinoud */
1903 1.1 reinoud lvextpos = implext->data + udf_rw32(implext->iu_l);
1904 1.1 reinoud memcpy(&lvext, lvextpos, sizeof(lvext));
1905 1.1 reinoud
1906 1.1 reinoud /* check if it was updated the last time */
1907 1.1 reinoud if (udf_rw64(lvext.unique_id_chk) == vat_unique_id) {
1908 1.1 reinoud lvinfo->num_files = lvext.num_files;
1909 1.1 reinoud lvinfo->num_directories = lvext.num_directories;
1910 1.1 reinoud udf_update_logvolname(lvext.logvol_id);
1911 1.1 reinoud } else {
1912 1.1 reinoud /* VAT LVExtension out of date */
1913 1.1 reinoud vat_writeout = 1;
1914 1.1 reinoud }
1915 1.1 reinoud } else {
1916 1.1 reinoud /* VAT 2.xy format */
1917 1.1 reinoud /* definition */
1918 1.1 reinoud vat = (struct udf_vat *) (*vat_contents);
1919 1.1 reinoud vat_offset = udf_rw16(vat->header_len);
1920 1.1 reinoud vat_entries = (vat_length - vat_offset)/4;
1921 1.1 reinoud
1922 1.1 reinoud if (heuristics) {
1923 1.1 reinoud if (vat->impl_use_len == 0) {
1924 1.1 reinoud uint32_t start_val;
1925 1.1 reinoud start_val = udf_rw32(*((uint32_t *) vat->data));
1926 1.1 reinoud if (start_val == 0x694d2a00) {
1927 1.1 reinoud /* "<0>*Mic"osoft Windows */
1928 1.1 reinoud pwarn("Heuristics found corrupted MS Windows VAT\n");
1929 1.1 reinoud if (ask(0, "Repair")) {
1930 1.1 reinoud vat->impl_use_len = udf_rw16(32);
1931 1.1 reinoud vat->header_len = udf_rw16(udf_rw16(vat->header_len) + 32);
1932 1.1 reinoud vat_offset += 32;
1933 1.1 reinoud vat_writeout = 1;
1934 1.1 reinoud }
1935 1.1 reinoud }
1936 1.1 reinoud }
1937 1.1 reinoud }
1938 1.1 reinoud assert(lvinfo);
1939 1.1 reinoud lvinfo->num_files = vat->num_files;
1940 1.1 reinoud lvinfo->num_directories = vat->num_directories;
1941 1.1 reinoud lvinfo->min_udf_readver = vat->min_udf_readver;
1942 1.1 reinoud lvinfo->min_udf_writever = vat->min_udf_writever;
1943 1.1 reinoud lvinfo->max_udf_writever = vat->max_udf_writever;
1944 1.1 reinoud
1945 1.1 reinoud udf_update_logvolname(vat->logvol_id);
1946 1.1 reinoud }
1947 1.1 reinoud
1948 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */
1949 1.1 reinoud //vat_writeout = 1;
1950 1.1 reinoud
1951 1.1 reinoud ok:
1952 1.1 reinoud /* extra sanity checking */
1953 1.1 reinoud if (tag_id == TAGID_FENTRY) {
1954 1.1 reinoud /* nothing checked as yet */
1955 1.1 reinoud } else {
1956 1.1 reinoud /*
1957 1.1 reinoud * The following VAT violations are ignored but demand a clean VAT
1958 1.1 reinoud * writeout for sanity
1959 1.1 reinoud */
1960 1.1 reinoud if (!is_zero(&dscr->efe.streamdir_icb, sizeof(struct long_ad))) {
1961 1.1 reinoud /* VAT specification violation:
1962 1.1 reinoud * VAT has no cleared streamdir reference */
1963 1.1 reinoud vat_writeout = 1;
1964 1.1 reinoud }
1965 1.1 reinoud if (!is_zero(&dscr->efe.ex_attr_icb, sizeof(struct long_ad))) {
1966 1.1 reinoud /* VAT specification violation:
1967 1.1 reinoud * VAT has no cleared extended attribute reference */
1968 1.1 reinoud vat_writeout = 1;
1969 1.1 reinoud }
1970 1.1 reinoud if (dscr->efe.obj_size != dscr->efe.inf_len) {
1971 1.1 reinoud /* VAT specification violation:
1972 1.1 reinoud * VAT has invalid object size */
1973 1.1 reinoud vat_writeout = 1;
1974 1.1 reinoud }
1975 1.1 reinoud }
1976 1.1 reinoud
1977 1.1 reinoud if (!vat_writeout) {
1978 1.1 reinoud context.logvol_integrity->lvint_next_unique_id = udf_rw64(vat_unique_id);
1979 1.1 reinoud context.logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED);
1980 1.1 reinoud context.logvol_integrity->time = *mtime;
1981 1.1 reinoud }
1982 1.1 reinoud
1983 1.1 reinoud context.unique_id = vat_unique_id;
1984 1.1 reinoud context.vat_allocated = UDF_ROUNDUP(vat_length, context.sector_size);
1985 1.1 reinoud context.vat_contents = *vat_contents;
1986 1.1 reinoud context.vat_start = vat_offset;
1987 1.1 reinoud context.vat_size = vat_offset + vat_entries * 4;
1988 1.1 reinoud
1989 1.1 reinoud out:
1990 1.1 reinoud if (error) {
1991 1.1 reinoud free(*vat_contents);
1992 1.1 reinoud *vat_contents = NULL;
1993 1.1 reinoud }
1994 1.1 reinoud
1995 1.1 reinoud return error;
1996 1.1 reinoud }
1997 1.1 reinoud
1998 1.1 reinoud
1999 1.1 reinoud #define VAT_BLK 256
2000 1.1 reinoud static int
2001 1.1 reinoud udf_search_vat(union udf_pmap *mapping, int log_part)
2002 1.1 reinoud {
2003 1.1 reinoud union dscrptr *vat_candidate, *accepted_vat;
2004 1.1 reinoud struct part_desc *pdesc;
2005 1.1 reinoud struct mmc_trackinfo *ti, *ti_s;
2006 1.1 reinoud uint32_t part_start;
2007 1.1 reinoud uint32_t vat_loc, early_vat_loc, late_vat_loc, accepted_vat_loc;
2008 1.1 reinoud uint32_t first_possible_vat_location, last_possible_vat_location;
2009 1.1 reinoud uint8_t *vat_contents, *accepted_vat_contents;
2010 1.1 reinoud int num_tracks, tracknr, found_a_VAT, valid_loc, error;
2011 1.1 reinoud
2012 1.1 reinoud /*
2013 1.1 reinoud * Start reading forward in blocks from the first possible vat
2014 1.1 reinoud * location. If not found in this block, start again a bit before
2015 1.1 reinoud * until we get a hit.
2016 1.1 reinoud */
2017 1.1 reinoud
2018 1.1 reinoud /* get complete list of all our valid ranges */
2019 1.1 reinoud ti_s = calloc(mmc_discinfo.num_tracks, sizeof(struct mmc_trackinfo));
2020 1.1 reinoud for (tracknr = 1; tracknr <= mmc_discinfo.num_tracks; tracknr++) {
2021 1.1 reinoud ti = &ti_s[tracknr];
2022 1.1 reinoud ti->tracknr = tracknr;
2023 1.1 reinoud (void) udf_update_trackinfo(ti);
2024 1.1 reinoud }
2025 1.1 reinoud
2026 1.1 reinoud /* derive our very first track number our base partition covers */
2027 1.1 reinoud pdesc = context.partitions[context.data_part];
2028 1.1 reinoud part_start = udf_rw32(pdesc->start_loc);
2029 1.1 reinoud for (int cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
2030 1.1 reinoud pdesc = context.partitions[cnt];
2031 1.1 reinoud if (!pdesc)
2032 1.1 reinoud continue;
2033 1.1 reinoud part_start = MIN(part_start, udf_rw32(pdesc->start_loc));
2034 1.1 reinoud }
2035 1.1 reinoud num_tracks = mmc_discinfo.num_tracks;
2036 1.1 reinoud for (tracknr = 1, ti = NULL; tracknr <= num_tracks; tracknr++) {
2037 1.1 reinoud ti = &ti_s[tracknr];
2038 1.1 reinoud if ((part_start >= ti->track_start) &&
2039 1.1 reinoud (part_start <= ti->track_start + ti->track_size))
2040 1.1 reinoud break;
2041 1.1 reinoud }
2042 1.1 reinoud context.first_ti_partition = *ti;
2043 1.1 reinoud
2044 1.1 reinoud first_possible_vat_location = context.first_ti_partition.track_start;
2045 1.1 reinoud last_possible_vat_location = context.last_ti.track_start +
2046 1.1 reinoud context.last_ti.track_size -
2047 1.1 reinoud context.last_ti.free_blocks + 1;
2048 1.1 reinoud
2049 1.1 reinoud /* initial guess is around 16 sectors back */
2050 1.1 reinoud late_vat_loc = last_possible_vat_location;
2051 1.1 reinoud early_vat_loc = MAX(late_vat_loc - 16, first_possible_vat_location);
2052 1.1 reinoud
2053 1.1 reinoud if (!preen)
2054 1.1 reinoud printf("Full VAT range search from %d to %d\n",
2055 1.1 reinoud first_possible_vat_location,
2056 1.1 reinoud last_possible_vat_location);
2057 1.1 reinoud
2058 1.1 reinoud vat_writeout = 0;
2059 1.1 reinoud accepted_vat = NULL;
2060 1.1 reinoud accepted_vat_contents = NULL;
2061 1.1 reinoud accepted_vat_loc = 0;
2062 1.1 reinoud do {
2063 1.1 reinoud vat_loc = early_vat_loc;
2064 1.1 reinoud if (!preen) {
2065 1.1 reinoud printf("\tChecking range %8d to %8d\n",
2066 1.1 reinoud early_vat_loc, late_vat_loc);
2067 1.1 reinoud fflush(stdout);
2068 1.1 reinoud }
2069 1.1 reinoud found_a_VAT = 0;
2070 1.1 reinoud while (vat_loc <= late_vat_loc) {
2071 1.1 reinoud if (print_info) {
2072 1.1 reinoud pwarn("\nchecking for VAT in sector %8d\n", vat_loc);
2073 1.1 reinoud print_info = 0;
2074 1.1 reinoud }
2075 1.1 reinoud /* check if its in readable range */
2076 1.1 reinoud valid_loc = 0;
2077 1.1 reinoud for (tracknr = 1; tracknr <= num_tracks; tracknr++) {
2078 1.1 reinoud ti = &ti_s[tracknr];
2079 1.1 reinoud if (!(ti->flags & MMC_TRACKINFO_BLANK) &&
2080 1.1 reinoud ((vat_loc >= ti->track_start) &&
2081 1.1 reinoud (vat_loc <= ti->track_start + ti->track_size))) {
2082 1.1 reinoud valid_loc = 1;
2083 1.1 reinoud break;
2084 1.1 reinoud }
2085 1.1 reinoud }
2086 1.1 reinoud if (!valid_loc) {
2087 1.1 reinoud vat_loc++;
2088 1.1 reinoud continue;
2089 1.1 reinoud }
2090 1.1 reinoud
2091 1.1 reinoud error = udf_read_dscr_phys(vat_loc, &vat_candidate);
2092 1.1 reinoud if (!vat_candidate)
2093 1.1 reinoud error = ENOENT;
2094 1.1 reinoud if (!error)
2095 1.1 reinoud error = udf_check_for_vat(vat_candidate);
2096 1.1 reinoud if (error) {
2097 1.1 reinoud vat_loc++; /* walk forward */
2098 1.1 reinoud continue;
2099 1.1 reinoud }
2100 1.1 reinoud
2101 1.1 reinoud if (accepted_vat) {
2102 1.1 reinoud /* check if newer vat time stamp is the same */
2103 1.1 reinoud if (udf_compare_mtimes(
2104 1.1 reinoud udf_file_mtime(vat_candidate),
2105 1.1 reinoud udf_file_mtime(accepted_vat)
2106 1.1 reinoud ) == 0) {
2107 1.1 reinoud free(vat_candidate);
2108 1.1 reinoud vat_loc++; /* walk forward */
2109 1.1 reinoud continue;
2110 1.1 reinoud }
2111 1.1 reinoud }
2112 1.1 reinoud
2113 1.1 reinoud /* check if its contents are OK */
2114 1.1 reinoud error = udf_extract_vat(
2115 1.1 reinoud vat_candidate, &vat_contents);
2116 1.1 reinoud if (error) {
2117 1.1 reinoud /* unlikely */
2118 1.1 reinoud // pwarn("Unreadable or malformed VAT encountered\n");
2119 1.1 reinoud free(vat_candidate);
2120 1.1 reinoud vat_loc++;
2121 1.1 reinoud continue;
2122 1.1 reinoud }
2123 1.1 reinoud /* accept new vat */
2124 1.1 reinoud free(accepted_vat);
2125 1.1 reinoud free(accepted_vat_contents);
2126 1.1 reinoud
2127 1.1 reinoud accepted_vat = vat_candidate;
2128 1.1 reinoud accepted_vat_contents = vat_contents;
2129 1.1 reinoud accepted_vat_loc = vat_loc;
2130 1.1 reinoud vat_candidate = NULL;
2131 1.1 reinoud vat_contents = NULL;
2132 1.1 reinoud
2133 1.1 reinoud found_a_VAT = 1;
2134 1.1 reinoud
2135 1.1 reinoud vat_loc++; /* walk forward */
2136 1.1 reinoud };
2137 1.1 reinoud
2138 1.1 reinoud if (found_a_VAT && accepted_vat) {
2139 1.1 reinoud /* VAT accepted */
2140 1.1 reinoud if (!preen)
2141 1.1 reinoud udf_print_vat_details(accepted_vat);
2142 1.1 reinoud if (vat_writeout)
2143 1.1 reinoud pwarn("\tVAT accepted but marked dirty\n");
2144 1.1 reinoud if (!preen && !vat_writeout)
2145 1.1 reinoud pwarn("\tLogical volume integrity state set to CLOSED\n");
2146 1.1 reinoud if (!search_older_vat)
2147 1.1 reinoud break;
2148 1.1 reinoud if (!ask_noauto(0, "\tSearch older VAT"))
2149 1.1 reinoud break;
2150 1.1 reinoud late_vat_loc = accepted_vat_loc - 1;
2151 1.1 reinoud } else {
2152 1.1 reinoud late_vat_loc = early_vat_loc - 1;
2153 1.1 reinoud }
2154 1.9 reinoud if (early_vat_loc == first_possible_vat_location)
2155 1.9 reinoud break;
2156 1.1 reinoud early_vat_loc = first_possible_vat_location;
2157 1.1 reinoud if (late_vat_loc > VAT_BLK)
2158 1.1 reinoud early_vat_loc = MAX(early_vat_loc, late_vat_loc - VAT_BLK);
2159 1.1 reinoud } while (late_vat_loc > first_possible_vat_location);
2160 1.1 reinoud
2161 1.1 reinoud if (!preen)
2162 1.1 reinoud printf("\n");
2163 1.1 reinoud
2164 1.1 reinoud undo_opening_session = 0;
2165 1.1 reinoud
2166 1.1 reinoud if (!accepted_vat) {
2167 1.6 riastrad if ((context.last_ti.sessionnr > 1) &&
2168 1.1 reinoud ask_noauto(0, "Undo opening of last session")) {
2169 1.1 reinoud undo_opening_session = 1;
2170 1.1 reinoud pwarn("Undoing opening of last session not implemented!\n");
2171 1.1 reinoud error = ENOENT;
2172 1.1 reinoud goto error_out;
2173 1.1 reinoud } else {
2174 1.1 reinoud pwarn("No valid VAT found!\n");
2175 1.1 reinoud error = ENOENT;
2176 1.1 reinoud goto error_out;
2177 1.1 reinoud }
2178 1.1 reinoud }
2179 1.1 reinoud if (last_possible_vat_location - accepted_vat_loc > 16) {
2180 1.1 reinoud assert(accepted_vat);
2181 1.1 reinoud pwarn("Selected VAT is not the latest or not at the end of "
2182 1.1 reinoud "track.\n");
2183 1.1 reinoud vat_writeout = 1;
2184 1.1 reinoud }
2185 1.1 reinoud
2186 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */
2187 1.1 reinoud //vat_writeout = 1;
2188 1.1 reinoud //udf_update_lvintd(UDF_INTEGRITY_OPEN);
2189 1.1 reinoud
2190 1.1 reinoud return 0;
2191 1.1 reinoud
2192 1.1 reinoud error_out:
2193 1.1 reinoud free(accepted_vat);
2194 1.1 reinoud free(accepted_vat_contents);
2195 1.1 reinoud
2196 1.1 reinoud return error;
2197 1.1 reinoud }
2198 1.1 reinoud
2199 1.1 reinoud /* ------------------------- sparables support ------------------------- */
2200 1.1 reinoud
2201 1.1 reinoud static int
2202 1.1 reinoud udf_read_spareables(union udf_pmap *mapping, int log_part)
2203 1.1 reinoud {
2204 1.1 reinoud union dscrptr *dscr;
2205 1.1 reinoud struct part_map_spare *pms = &mapping->pms;
2206 1.1 reinoud uint32_t lb_num;
2207 1.1 reinoud int spar, error;
2208 1.1 reinoud
2209 1.1 reinoud for (spar = 0; spar < pms->n_st; spar++) {
2210 1.1 reinoud lb_num = pms->st_loc[spar];
2211 1.1 reinoud error = udf_read_dscr_phys(lb_num, &dscr);
2212 1.1 reinoud if (error && !preen)
2213 1.1 reinoud pwarn("Error reading spareable table %d\n", spar);
2214 1.1 reinoud if (!error && dscr) {
2215 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_SPARING_TABLE) {
2216 1.1 reinoud free(context.sparing_table);
2217 1.1 reinoud context.sparing_table = &dscr->spt;
2218 1.1 reinoud dscr = NULL;
2219 1.1 reinoud break; /* we're done */
2220 1.1 reinoud }
2221 1.1 reinoud }
2222 1.1 reinoud free(dscr);
2223 1.1 reinoud }
2224 1.1 reinoud if (context.sparing_table == NULL)
2225 1.1 reinoud return ENOENT;
2226 1.1 reinoud return 0;
2227 1.1 reinoud }
2228 1.1 reinoud
2229 1.1 reinoud /* ------------------------- metadata support ------------------------- */
2230 1.1 reinoud
2231 1.1 reinoud static bool
2232 1.1 reinoud udf_metadata_node_supported(void)
2233 1.1 reinoud {
2234 1.1 reinoud struct extfile_entry *efe;
2235 1.1 reinoud struct short_ad *short_ad;
2236 1.1 reinoud uint32_t len;
2237 1.1 reinoud uint32_t flags;
2238 1.1 reinoud uint8_t *data_pos;
2239 1.1 reinoud int dscr_size, l_ea, l_ad, icbflags, addr_type;
2240 1.1 reinoud
2241 1.1 reinoud /* we have to look into the file's allocation descriptors */
2242 1.1 reinoud
2243 1.1 reinoud efe = context.meta_file;
2244 1.1 reinoud dscr_size = sizeof(struct extfile_entry) - 1;
2245 1.1 reinoud l_ea = udf_rw32(efe->l_ea);
2246 1.1 reinoud l_ad = udf_rw32(efe->l_ad);
2247 1.1 reinoud
2248 1.1 reinoud icbflags = udf_rw16(efe->icbtag.flags);
2249 1.1 reinoud addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
2250 1.1 reinoud if (addr_type != UDF_ICB_SHORT_ALLOC) {
2251 1.1 reinoud warnx("specification violation: metafile not using"
2252 1.1 reinoud "short allocs");
2253 1.1 reinoud return false;
2254 1.1 reinoud }
2255 1.1 reinoud
2256 1.1 reinoud data_pos = (uint8_t *) context.meta_file + dscr_size + l_ea;
2257 1.1 reinoud short_ad = (struct short_ad *) data_pos;
2258 1.1 reinoud while (l_ad > 0) {
2259 1.1 reinoud len = udf_rw32(short_ad->len);
2260 1.1 reinoud flags = UDF_EXT_FLAGS(len);
2261 1.1 reinoud if (flags == UDF_EXT_REDIRECT) {
2262 1.1 reinoud warnx("implementation limit: no support for "
2263 1.1 reinoud "extent redirections in metadata file");
2264 1.1 reinoud return false;
2265 1.1 reinoud }
2266 1.1 reinoud short_ad++;
2267 1.1 reinoud l_ad -= sizeof(struct short_ad);
2268 1.1 reinoud }
2269 1.1 reinoud /* we passed all of them */
2270 1.1 reinoud return true;
2271 1.1 reinoud }
2272 1.1 reinoud
2273 1.1 reinoud
2274 1.1 reinoud static int
2275 1.1 reinoud udf_read_metadata_nodes(union udf_pmap *mapping, int log_part)
2276 1.1 reinoud {
2277 1.1 reinoud union dscrptr *dscr1, *dscr2, *dscr3;
2278 1.1 reinoud struct part_map_meta *pmm = &mapping->pmm;
2279 1.1 reinoud uint16_t raw_phys_part, phys_part;
2280 1.1 reinoud int tagid, file_type, error;
2281 1.1 reinoud
2282 1.1 reinoud /*
2283 1.1 reinoud * BUGALERT: some rogue implementations use random physical
2284 1.1 reinoud * partition numbers to break other implementations so lookup
2285 1.1 reinoud * the number.
2286 1.1 reinoud */
2287 1.1 reinoud
2288 1.1 reinoud raw_phys_part = udf_rw16(pmm->part_num);
2289 1.1 reinoud phys_part = udf_find_raw_phys(raw_phys_part);
2290 1.1 reinoud
2291 1.1 reinoud error = udf_read_dscr_virt(layout.meta_file, phys_part, &dscr1);
2292 1.1 reinoud if (!error) {
2293 1.1 reinoud tagid = udf_rw16(dscr1->tag.id);
2294 1.1 reinoud file_type = dscr1->efe.icbtag.file_type;
2295 1.1 reinoud if ((tagid != TAGID_EXTFENTRY) ||
2296 1.1 reinoud (file_type != UDF_ICB_FILETYPE_META_MAIN))
2297 1.1 reinoud error = ENOENT;
2298 1.1 reinoud }
2299 1.1 reinoud if (error) {
2300 1.1 reinoud pwarn("Bad primary metadata file descriptor\n");
2301 1.1 reinoud free(dscr1);
2302 1.1 reinoud dscr1 = NULL;
2303 1.1 reinoud }
2304 1.1 reinoud
2305 1.1 reinoud error = udf_read_dscr_virt(layout.meta_mirror, phys_part, &dscr2);
2306 1.1 reinoud if (!error) {
2307 1.1 reinoud tagid = udf_rw16(dscr2->tag.id);
2308 1.1 reinoud file_type = dscr2->efe.icbtag.file_type;
2309 1.1 reinoud if ((tagid != TAGID_EXTFENTRY) ||
2310 1.1 reinoud (file_type != UDF_ICB_FILETYPE_META_MIRROR))
2311 1.1 reinoud error = ENOENT;
2312 1.1 reinoud }
2313 1.1 reinoud if (error) {
2314 1.1 reinoud pwarn("Bad mirror metadata file descriptor\n");
2315 1.1 reinoud free(dscr2);
2316 1.1 reinoud dscr2 = NULL;
2317 1.1 reinoud }
2318 1.1 reinoud
2319 1.1 reinoud if ((dscr1 == NULL) && (dscr2 == NULL)) {
2320 1.1 reinoud pwarn("No valid metadata file descriptors found!\n");
2321 1.1 reinoud return -1;
2322 1.1 reinoud }
2323 1.1 reinoud
2324 1.1 reinoud error = 0;
2325 1.1 reinoud if ((dscr1 == NULL) && dscr2) {
2326 1.1 reinoud dscr1 = malloc(context.sector_size);
2327 1.1 reinoud memcpy(dscr1, dscr2, context.sector_size);
2328 1.1 reinoud dscr1->efe.icbtag.file_type = UDF_ICB_FILETYPE_META_MAIN;
2329 1.1 reinoud if (ask(1, "Fix up bad primary metadata file descriptor")) {
2330 1.1 reinoud error = udf_write_dscr_virt(dscr1,
2331 1.1 reinoud layout.meta_file, phys_part, 1);
2332 1.1 reinoud }
2333 1.1 reinoud }
2334 1.1 reinoud if (dscr1 && (dscr2 == NULL)) {
2335 1.1 reinoud dscr2 = malloc(context.sector_size);
2336 1.1 reinoud memcpy(dscr2, dscr1, context.sector_size);
2337 1.1 reinoud dscr2->efe.icbtag.file_type = UDF_ICB_FILETYPE_META_MIRROR;
2338 1.1 reinoud if (ask(1, "Fix up bad mirror metadata file descriptor")) {
2339 1.1 reinoud error = udf_write_dscr_virt(dscr2,
2340 1.1 reinoud layout.meta_mirror, phys_part, 1);
2341 1.1 reinoud }
2342 1.1 reinoud }
2343 1.1 reinoud if (error)
2344 1.1 reinoud pwarn("Copying metadata file descriptor failed, "
2345 1.1 reinoud "trying to continue\n");
2346 1.1 reinoud
2347 1.1 reinoud context.meta_file = &dscr1->efe;
2348 1.1 reinoud context.meta_mirror = &dscr2->efe;
2349 1.1 reinoud
2350 1.1 reinoud dscr3 = NULL;
2351 1.1 reinoud if (layout.meta_bitmap != 0xffffffff) {
2352 1.1 reinoud error = udf_read_dscr_virt(layout.meta_bitmap, phys_part, &dscr3);
2353 1.1 reinoud if (!error) {
2354 1.1 reinoud tagid = udf_rw16(dscr3->tag.id);
2355 1.1 reinoud file_type = dscr3->efe.icbtag.file_type;
2356 1.1 reinoud if ((tagid != TAGID_EXTFENTRY) ||
2357 1.1 reinoud (file_type != UDF_ICB_FILETYPE_META_BITMAP))
2358 1.1 reinoud error = ENOENT;
2359 1.1 reinoud }
2360 1.1 reinoud if (error) {
2361 1.1 reinoud pwarn("Bad metadata bitmap file descriptor\n");
2362 1.1 reinoud free(dscr3);
2363 1.1 reinoud dscr3 = NULL;
2364 1.1 reinoud }
2365 1.1 reinoud
2366 1.1 reinoud if (dscr3 == NULL) {
2367 1.1 reinoud pwarn("implementation limit: can't repair missing or "
2368 1.1 reinoud "damaged metadata bitmap descriptor\n");
2369 1.1 reinoud return -1;
2370 1.1 reinoud }
2371 1.1 reinoud
2372 1.1 reinoud context.meta_bitmap = &dscr3->efe;
2373 1.1 reinoud }
2374 1.1 reinoud
2375 1.1 reinoud /* TODO early check if meta_file has allocation extent redirections */
2376 1.1 reinoud if (!udf_metadata_node_supported())
2377 1.1 reinoud return EINVAL;
2378 1.1 reinoud
2379 1.1 reinoud return 0;
2380 1.1 reinoud }
2381 1.1 reinoud
2382 1.1 reinoud /* ------------------------- VDS readin ------------------------- */
2383 1.1 reinoud
2384 1.1 reinoud /* checks if the VDS information is correct and complete */
2385 1.1 reinoud static int
2386 1.1 reinoud udf_process_vds(void) {
2387 1.1 reinoud union dscrptr *dscr;
2388 1.1 reinoud union udf_pmap *mapping;
2389 1.1 reinoud struct part_desc *pdesc;
2390 1.1 reinoud struct long_ad fsd_loc;
2391 1.1 reinoud uint8_t *pmap_pos;
2392 1.1 reinoud char *domain_name, *map_name;
2393 1.6 riastrad const char *check_name;
2394 1.1 reinoud int pmap_stype, pmap_size;
2395 1.1 reinoud int pmap_type, log_part, phys_part, raw_phys_part; //, maps_on;
2396 1.1 reinoud int n_pm, n_phys, n_virt, n_spar, n_meta;
2397 1.1 reinoud int len, error;
2398 1.1 reinoud
2399 1.1 reinoud /* we need at least an anchor (trivial, but for safety) */
2400 1.1 reinoud if (context.anchors[0] == NULL) {
2401 1.1 reinoud pwarn("sanity check: no anchors?\n");
2402 1.1 reinoud return EINVAL;
2403 1.1 reinoud }
2404 1.1 reinoud
2405 1.1 reinoud /* we need at least one primary and one logical volume descriptor */
2406 1.1 reinoud if ((context.primary_vol == NULL) || (context.logical_vol) == NULL) {
2407 1.1 reinoud pwarn("sanity check: missing primary or missing logical volume\n");
2408 1.1 reinoud return EINVAL;
2409 1.1 reinoud }
2410 1.1 reinoud
2411 1.1 reinoud /* we need at least one partition descriptor */
2412 1.1 reinoud if (context.partitions[0] == NULL) {
2413 1.1 reinoud pwarn("sanity check: missing partition descriptor\n");
2414 1.1 reinoud return EINVAL;
2415 1.1 reinoud }
2416 1.1 reinoud
2417 1.1 reinoud /* check logical volume sector size versus device sector size */
2418 1.1 reinoud if (udf_rw32(context.logical_vol->lb_size) != context.sector_size) {
2419 1.1 reinoud pwarn("sanity check: lb_size != sector size\n");
2420 1.1 reinoud return EINVAL;
2421 1.1 reinoud }
2422 1.1 reinoud
2423 1.1 reinoud /* check domain name, should never fail */
2424 1.1 reinoud domain_name = (char *) context.logical_vol->domain_id.id;
2425 1.1 reinoud if (strncmp(domain_name, "*OSTA UDF Compliant", 20)) {
2426 1.1 reinoud pwarn("sanity check: disc not OSTA UDF Compliant, aborting\n");
2427 1.1 reinoud return EINVAL;
2428 1.1 reinoud }
2429 1.1 reinoud
2430 1.1 reinoud /* retrieve logical volume integrity sequence */
2431 1.1 reinoud udf_retrieve_lvint();
2432 1.1 reinoud
2433 1.1 reinoud /* check if we support this disc, ie less or equal to 0x250 */
2434 1.1 reinoud if (udf_rw16(context.logvol_info->min_udf_writever) > 0x250) {
2435 1.1 reinoud pwarn("implementation limit: minimum write version UDF 2.60 "
2436 1.1 reinoud "and on are not supported\n");
2437 1.1 reinoud return EINVAL;
2438 1.1 reinoud }
2439 1.1 reinoud
2440 1.1 reinoud /*
2441 1.1 reinoud * check logvol mappings: effective virt->log partmap translation
2442 1.1 reinoud * check and recording of the mapping results. Saves expensive
2443 1.1 reinoud * strncmp() in tight places.
2444 1.1 reinoud */
2445 1.1 reinoud n_pm = udf_rw32(context.logical_vol->n_pm); /* num partmaps */
2446 1.1 reinoud pmap_pos = context.logical_vol->maps;
2447 1.1 reinoud
2448 1.1 reinoud if (n_pm > UDF_PMAPS) {
2449 1.1 reinoud pwarn("implementation limit: too many logvol mappings\n");
2450 1.1 reinoud return EINVAL;
2451 1.1 reinoud }
2452 1.1 reinoud
2453 1.1 reinoud /* count types and set partition numbers */
2454 1.1 reinoud context.data_part = context.metadata_part = context.fids_part = 0;
2455 1.1 reinoud n_phys = n_virt = n_spar = n_meta = 0;
2456 1.1 reinoud for (log_part = 0; log_part < n_pm; log_part++) {
2457 1.1 reinoud mapping = (union udf_pmap *) pmap_pos;
2458 1.1 reinoud pmap_stype = pmap_pos[0];
2459 1.1 reinoud pmap_size = pmap_pos[1];
2460 1.1 reinoud switch (pmap_stype) {
2461 1.1 reinoud case 1: /* physical mapping */
2462 1.1 reinoud /* volseq = udf_rw16(mapping->pm1.vol_seq_num); */
2463 1.1 reinoud raw_phys_part = udf_rw16(mapping->pm1.part_num);
2464 1.1 reinoud pmap_type = UDF_VTOP_TYPE_PHYS;
2465 1.1 reinoud n_phys++;
2466 1.1 reinoud context.data_part = log_part;
2467 1.1 reinoud context.metadata_part = log_part;
2468 1.1 reinoud context.fids_part = log_part;
2469 1.1 reinoud break;
2470 1.1 reinoud case 2: /* virtual/sparable/meta mapping */
2471 1.1 reinoud map_name = (char *) mapping->pm2.part_id.id;
2472 1.1 reinoud /* volseq = udf_rw16(mapping->pm2.vol_seq_num); */
2473 1.1 reinoud raw_phys_part = udf_rw16(mapping->pm2.part_num);
2474 1.1 reinoud pmap_type = UDF_VTOP_TYPE_UNKNOWN;
2475 1.1 reinoud len = UDF_REGID_ID_SIZE;
2476 1.1 reinoud
2477 1.1 reinoud check_name = "*UDF Virtual Partition";
2478 1.1 reinoud if (strncmp(map_name, check_name, len) == 0) {
2479 1.1 reinoud pmap_type = UDF_VTOP_TYPE_VIRT;
2480 1.1 reinoud n_virt++;
2481 1.1 reinoud context.metadata_part = log_part;
2482 1.1 reinoud context.format_flags |= FORMAT_VAT;
2483 1.1 reinoud break;
2484 1.1 reinoud }
2485 1.1 reinoud check_name = "*UDF Sparable Partition";
2486 1.1 reinoud if (strncmp(map_name, check_name, len) == 0) {
2487 1.1 reinoud pmap_type = UDF_VTOP_TYPE_SPAREABLE;
2488 1.1 reinoud n_spar++;
2489 1.1 reinoud layout.spareable_blockingnr = udf_rw16(mapping->pms.packet_len);
2490 1.1 reinoud
2491 1.1 reinoud context.data_part = log_part;
2492 1.1 reinoud context.metadata_part = log_part;
2493 1.1 reinoud context.fids_part = log_part;
2494 1.1 reinoud context.format_flags |= FORMAT_SPAREABLE;
2495 1.1 reinoud break;
2496 1.1 reinoud }
2497 1.1 reinoud check_name = "*UDF Metadata Partition";
2498 1.1 reinoud if (strncmp(map_name, check_name, len) == 0) {
2499 1.1 reinoud pmap_type = UDF_VTOP_TYPE_META;
2500 1.1 reinoud n_meta++;
2501 1.1 reinoud layout.meta_file = udf_rw32(mapping->pmm.meta_file_lbn);
2502 1.1 reinoud layout.meta_mirror = udf_rw32(mapping->pmm.meta_mirror_file_lbn);
2503 1.1 reinoud layout.meta_bitmap = udf_rw32(mapping->pmm.meta_bitmap_file_lbn);
2504 1.1 reinoud layout.meta_blockingnr = udf_rw32(mapping->pmm.alloc_unit_size);
2505 1.1 reinoud layout.meta_alignment = udf_rw16(mapping->pmm.alignment_unit_size);
2506 1.1 reinoud /* XXX metadata_flags in mapping->pmm.flags? XXX */
2507 1.1 reinoud
2508 1.1 reinoud context.metadata_part = log_part;
2509 1.1 reinoud context.fids_part = log_part;
2510 1.1 reinoud context.format_flags |= FORMAT_META;
2511 1.1 reinoud break;
2512 1.1 reinoud }
2513 1.1 reinoud break;
2514 1.1 reinoud default:
2515 1.1 reinoud return EINVAL;
2516 1.1 reinoud }
2517 1.1 reinoud
2518 1.1 reinoud /*
2519 1.1 reinoud * BUGALERT: some rogue implementations use random physical
2520 1.1 reinoud * partition numbers to break other implementations so lookup
2521 1.1 reinoud * the number.
2522 1.1 reinoud */
2523 1.1 reinoud phys_part = udf_find_raw_phys(raw_phys_part);
2524 1.1 reinoud
2525 1.1 reinoud if (phys_part == UDF_PARTITIONS) {
2526 1.1 reinoud pwarn("implementation limit: too many partitions\n");
2527 1.1 reinoud return EINVAL;
2528 1.1 reinoud }
2529 1.1 reinoud if (pmap_type == UDF_VTOP_TYPE_UNKNOWN) {
2530 1.1 reinoud pwarn("implementation limit: encountered unknown "
2531 1.1 reinoud "logvol mapping `%s`!\n", map_name);
2532 1.1 reinoud return EINVAL;
2533 1.1 reinoud }
2534 1.1 reinoud
2535 1.1 reinoud context.vtop [log_part] = phys_part;
2536 1.1 reinoud context.vtop_tp[log_part] = pmap_type;
2537 1.1 reinoud
2538 1.1 reinoud pmap_pos += pmap_size;
2539 1.1 reinoud }
2540 1.1 reinoud /* not winning the beauty contest */
2541 1.1 reinoud context.vtop_tp[UDF_VTOP_RAWPART] = UDF_VTOP_TYPE_RAW;
2542 1.1 reinoud
2543 1.1 reinoud /* test some basic UDF assertions/requirements */
2544 1.1 reinoud if ((n_virt > 1) || (n_spar > 1) || (n_meta > 1)) {
2545 1.1 reinoud pwarn("Sanity check: format error, more than one "
2546 1.1 reinoud "virtual, sparable or meta mapping\n");
2547 1.1 reinoud return EINVAL;
2548 1.1 reinoud }
2549 1.1 reinoud
2550 1.1 reinoud if (n_virt) {
2551 1.1 reinoud if ((n_phys == 0) || n_spar || n_meta) {
2552 1.1 reinoud pwarn("Sanity check: format error, no backing for "
2553 1.1 reinoud "virtual partition\n");
2554 1.1 reinoud return EINVAL;
2555 1.1 reinoud }
2556 1.1 reinoud }
2557 1.1 reinoud if (n_spar + n_phys == 0) {
2558 1.1 reinoud pwarn("Sanity check: can't combine a sparable and a "
2559 1.1 reinoud "physical partition\n");
2560 1.1 reinoud return EINVAL;
2561 1.1 reinoud }
2562 1.1 reinoud
2563 1.1 reinoud /* print format type as derived */
2564 1.1 reinoud if (!preen) {
2565 1.1 reinoud char bits[255];
2566 1.1 reinoud snprintb(bits, sizeof(bits), FORMAT_FLAGBITS, context.format_flags);
2567 1.1 reinoud printf("Format flags %s\n\n", bits);
2568 1.1 reinoud }
2569 1.1 reinoud
2570 1.1 reinoud /* read supporting tables */
2571 1.1 reinoud pmap_pos = context.logical_vol->maps;
2572 1.1 reinoud for (log_part = 0; log_part < n_pm; log_part++) {
2573 1.1 reinoud mapping = (union udf_pmap *) pmap_pos;
2574 1.1 reinoud pmap_size = pmap_pos[1];
2575 1.1 reinoud switch (context.vtop_tp[log_part]) {
2576 1.1 reinoud case UDF_VTOP_TYPE_PHYS :
2577 1.1 reinoud /* nothing */
2578 1.1 reinoud break;
2579 1.1 reinoud case UDF_VTOP_TYPE_VIRT :
2580 1.1 reinoud /* search and load VAT */
2581 1.1 reinoud error = udf_search_vat(mapping, log_part);
2582 1.1 reinoud if (error) {
2583 1.1 reinoud pwarn("Couldn't find virtual allocation table\n");
2584 1.1 reinoud return ENOENT;
2585 1.1 reinoud }
2586 1.1 reinoud break;
2587 1.1 reinoud case UDF_VTOP_TYPE_SPAREABLE :
2588 1.1 reinoud /* load one of the sparable tables */
2589 1.1 reinoud error = udf_read_spareables(mapping, log_part);
2590 1.1 reinoud if (error) {
2591 1.1 reinoud pwarn("Couldn't load sparable blocks tables\n");
2592 1.1 reinoud return ENOENT;
2593 1.1 reinoud }
2594 1.1 reinoud break;
2595 1.1 reinoud case UDF_VTOP_TYPE_META :
2596 1.1 reinoud /* load the associated file descriptors */
2597 1.1 reinoud error = udf_read_metadata_nodes(mapping, log_part);
2598 1.1 reinoud if (error) {
2599 1.1 reinoud pwarn("Couldn't read in the metadata descriptors\n");
2600 1.1 reinoud return ENOENT;
2601 1.1 reinoud }
2602 1.1 reinoud
2603 1.1 reinoud /*
2604 1.1 reinoud * We have to extract the partition size from the meta
2605 1.1 reinoud * data file length
2606 1.1 reinoud */
2607 1.1 reinoud context.part_size[log_part] =
2608 1.8 reinoud udf_rw64(context.meta_file->inf_len) / context.sector_size;
2609 1.1 reinoud break;
2610 1.1 reinoud default:
2611 1.1 reinoud break;
2612 1.1 reinoud }
2613 1.1 reinoud pmap_pos += pmap_size;
2614 1.1 reinoud }
2615 1.1 reinoud
2616 1.1 reinoud /*
2617 1.1 reinoud * Free/unallocated space bitmap readin delayed; the FS might be
2618 1.1 reinoud * closed already; no need to read in copious amount of data only to
2619 1.1 reinoud * not use it later.
2620 1.1 reinoud *
2621 1.1 reinoud * For now, extract partition sizes in our context
2622 1.1 reinoud */
2623 1.1 reinoud for (int cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
2624 1.1 reinoud pdesc = context.partitions[cnt];
2625 1.1 reinoud if (!pdesc)
2626 1.1 reinoud continue;
2627 1.1 reinoud
2628 1.1 reinoud context.part_size[cnt] = udf_rw32(pdesc->part_len);
2629 1.1 reinoud context.part_unalloc_bits[cnt] = NULL;
2630 1.1 reinoud }
2631 1.1 reinoud
2632 1.1 reinoud /* read file set descriptor */
2633 1.1 reinoud fsd_loc = context.logical_vol->lv_fsd_loc;
2634 1.1 reinoud error = udf_read_dscr_virt(
2635 1.1 reinoud udf_rw32(fsd_loc.loc.lb_num),
2636 1.1 reinoud udf_rw16(fsd_loc.loc.part_num), &dscr);
2637 1.1 reinoud if (error) {
2638 1.1 reinoud pwarn("Couldn't read in file set descriptor\n");
2639 1.1 reinoud pwarn("implementation limit: can't fix this\n");
2640 1.1 reinoud return ENOENT;
2641 1.1 reinoud }
2642 1.1 reinoud if (udf_rw16(dscr->tag.id) != TAGID_FSD) {
2643 1.1 reinoud pwarn("Expected fsd at (p %d, lb %d)\n",
2644 1.1 reinoud udf_rw16(fsd_loc.loc.part_num),
2645 1.1 reinoud udf_rw32(fsd_loc.loc.lb_num));
2646 1.1 reinoud pwarn("File set descriptor not pointing to a file set!\n");
2647 1.1 reinoud return ENOENT;
2648 1.1 reinoud }
2649 1.1 reinoud context.fileset_desc = &dscr->fsd;
2650 1.1 reinoud
2651 1.1 reinoud /* signal its OK for now */
2652 1.1 reinoud return 0;
2653 1.1 reinoud }
2654 1.1 reinoud
2655 1.1 reinoud
2656 1.1 reinoud #define UDF_UPDATE_DSCR(name, dscr) \
2657 1.1 reinoud if (name) {\
2658 1.1 reinoud free (name); \
2659 1.1 reinoud updated = 1; \
2660 1.1 reinoud } \
2661 1.1 reinoud name = calloc(1, dscr_size); \
2662 1.1 reinoud memcpy(name, dscr, dscr_size);
2663 1.1 reinoud
2664 1.1 reinoud static void
2665 1.1 reinoud udf_process_vds_descriptor(union dscrptr *dscr, int dscr_size) {
2666 1.1 reinoud struct pri_vol_desc *pri;
2667 1.1 reinoud struct logvol_desc *lvd;
2668 1.1 reinoud uint16_t raw_phys_part, phys_part;
2669 1.1 reinoud int updated = 0;
2670 1.1 reinoud
2671 1.1 reinoud switch (udf_rw16(dscr->tag.id)) {
2672 1.1 reinoud case TAGID_PRI_VOL : /* primary partition */
2673 1.1 reinoud UDF_UPDATE_DSCR(context.primary_vol, dscr);
2674 1.1 reinoud pri = context.primary_vol;
2675 1.1 reinoud
2676 1.1 reinoud context.primary_name = malloc(32);
2677 1.1 reinoud context.volset_name = malloc(128);
2678 1.1 reinoud
2679 1.1 reinoud udf_to_unix_name(context.volset_name, 32, pri->volset_id, 32,
2680 1.1 reinoud &pri->desc_charset);
2681 1.1 reinoud udf_to_unix_name(context.primary_name, 128, pri->vol_id, 128,
2682 1.1 reinoud &pri->desc_charset);
2683 1.1 reinoud
2684 1.1 reinoud if (!preen && !updated) {
2685 1.1 reinoud pwarn("Volume set `%s`\n", context.volset_name);
2686 1.1 reinoud pwarn("Primary volume `%s`\n", context.primary_name);
2687 1.1 reinoud }
2688 1.1 reinoud break;
2689 1.1 reinoud case TAGID_LOGVOL : /* logical volume */
2690 1.1 reinoud UDF_UPDATE_DSCR(context.logical_vol, dscr);
2691 1.1 reinoud /* could check lvd->domain_id */
2692 1.1 reinoud lvd = context.logical_vol;
2693 1.1 reinoud context.logvol_name = malloc(128);
2694 1.1 reinoud
2695 1.1 reinoud udf_to_unix_name(context.logvol_name, 128, lvd->logvol_id, 128,
2696 1.1 reinoud &lvd->desc_charset);
2697 1.1 reinoud
2698 1.1 reinoud if (!preen && !updated)
2699 1.1 reinoud pwarn("Logical volume `%s`\n", context.logvol_name);
2700 1.1 reinoud break;
2701 1.1 reinoud case TAGID_UNALLOC_SPACE : /* unallocated space */
2702 1.1 reinoud UDF_UPDATE_DSCR(context.unallocated, dscr);
2703 1.1 reinoud break;
2704 1.1 reinoud case TAGID_IMP_VOL : /* implementation */
2705 1.1 reinoud UDF_UPDATE_DSCR(context.implementation, dscr);
2706 1.1 reinoud break;
2707 1.1 reinoud case TAGID_PARTITION : /* partition(s) */
2708 1.1 reinoud /* not much use if its not allocated */
2709 1.1 reinoud if ((udf_rw16(dscr->pd.flags) & UDF_PART_FLAG_ALLOCATED) == 0) {
2710 1.1 reinoud pwarn("Ignoring unallocated partition\n");
2711 1.1 reinoud break;
2712 1.1 reinoud }
2713 1.1 reinoud raw_phys_part = udf_rw16(dscr->pd.part_num);
2714 1.1 reinoud phys_part = udf_find_raw_phys(raw_phys_part);
2715 1.1 reinoud
2716 1.1 reinoud if (phys_part >= UDF_PARTITIONS) {
2717 1.1 reinoud pwarn("Too many physical partitions, ignoring\n");
2718 1.1 reinoud break;
2719 1.1 reinoud }
2720 1.1 reinoud UDF_UPDATE_DSCR(context.partitions[phys_part], dscr);
2721 1.1 reinoud break;
2722 1.1 reinoud case TAGID_TERM : /* terminator */
2723 1.1 reinoud break;
2724 1.1 reinoud case TAGID_VOL : /* volume space ext */
2725 1.1 reinoud pwarn("Ignoring VDS extender\n");
2726 1.1 reinoud break;
2727 1.1 reinoud default :
2728 1.1 reinoud pwarn("Unknown VDS type %d found, ignored\n",
2729 1.1 reinoud udf_rw16(dscr->tag.id));
2730 1.1 reinoud }
2731 1.1 reinoud }
2732 1.1 reinoud
2733 1.1 reinoud
2734 1.1 reinoud static void
2735 1.1 reinoud udf_read_vds_extent(union dscrptr *dscr, int vds_size) {
2736 1.1 reinoud uint8_t *pos;
2737 1.1 reinoud int sector_size = context.sector_size;
2738 1.1 reinoud int dscr_size;
2739 1.1 reinoud
2740 1.1 reinoud pos = (uint8_t *) dscr;
2741 1.1 reinoud while (vds_size) {
2742 1.1 reinoud /* process the descriptor */
2743 1.1 reinoud dscr = (union dscrptr *) pos;
2744 1.1 reinoud
2745 1.1 reinoud /* empty block terminates */
2746 1.1 reinoud if (is_zero(dscr, sector_size))
2747 1.1 reinoud return;
2748 1.1 reinoud
2749 1.1 reinoud /* terminator terminates */
2750 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_TERM)
2751 1.1 reinoud return;
2752 1.1 reinoud
2753 1.1 reinoud if (udf_check_tag(dscr))
2754 1.1 reinoud pwarn("Bad descriptor sum in vds, ignoring\n");
2755 1.1 reinoud
2756 1.1 reinoud dscr_size = udf_tagsize(dscr, sector_size);
2757 1.1 reinoud if (udf_check_tag_payload(dscr, dscr_size))
2758 1.1 reinoud pwarn("Bad descriptor CRC in vds, ignoring\n");
2759 1.1 reinoud
2760 1.1 reinoud udf_process_vds_descriptor(dscr, dscr_size);
2761 1.1 reinoud
2762 1.1 reinoud pos += dscr_size;
2763 1.1 reinoud vds_size -= dscr_size;
2764 1.1 reinoud }
2765 1.1 reinoud }
2766 1.1 reinoud
2767 1.1 reinoud
2768 1.1 reinoud static int
2769 1.1 reinoud udf_copy_VDS_area(void *destbuf, void *srcbuf)
2770 1.1 reinoud {
2771 1.1 reinoud pwarn("TODO implement VDS copy area, signalling success\n");
2772 1.1 reinoud return 0;
2773 1.1 reinoud }
2774 1.1 reinoud
2775 1.1 reinoud
2776 1.1 reinoud /* XXX why two buffers and not just read descritor by descriptor XXX */
2777 1.1 reinoud static int
2778 1.1 reinoud udf_check_VDS_areas(void) {
2779 1.1 reinoud union dscrptr *vds1_buf, *vds2_buf;
2780 1.1 reinoud int vds1_size, vds2_size;
2781 1.1 reinoud int error, error1, error2;
2782 1.1 reinoud
2783 1.1 reinoud vds1_size = layout.vds1_size * context.sector_size;
2784 1.1 reinoud vds2_size = layout.vds2_size * context.sector_size;
2785 1.1 reinoud vds1_buf = calloc(1, vds1_size);
2786 1.1 reinoud vds2_buf = calloc(1, vds2_size);
2787 1.1 reinoud assert(vds1_buf); assert(vds2_buf);
2788 1.1 reinoud
2789 1.1 reinoud error1 = udf_read_phys(vds1_buf, layout.vds1, layout.vds1_size);
2790 1.1 reinoud error2 = udf_read_phys(vds2_buf, layout.vds2, layout.vds2_size);
2791 1.1 reinoud
2792 1.1 reinoud if (error1 && error2) {
2793 1.1 reinoud pwarn("Can't read both volume descriptor areas!\n");
2794 1.1 reinoud return -1;
2795 1.1 reinoud }
2796 1.1 reinoud
2797 1.1 reinoud if (!error1) {
2798 1.1 reinoud /* retrieve data from VDS 1 */
2799 1.1 reinoud udf_read_vds_extent(vds1_buf, vds1_size);
2800 1.1 reinoud context.vds_buf = vds1_buf;
2801 1.1 reinoud context.vds_size = vds1_size;
2802 1.1 reinoud free(vds2_buf);
2803 1.1 reinoud }
2804 1.1 reinoud if (!error2) {
2805 1.1 reinoud /* retrieve data from VDS 2 */
2806 1.1 reinoud udf_read_vds_extent(vds2_buf, vds2_size);
2807 1.1 reinoud context.vds_buf = vds2_buf;
2808 1.1 reinoud context.vds_size = vds2_size;
2809 1.1 reinoud free(vds1_buf);
2810 1.1 reinoud }
2811 1.1 reinoud /* check if all is correct and complete */
2812 1.1 reinoud error = udf_process_vds();
2813 1.1 reinoud if (error)
2814 1.1 reinoud return error;
2815 1.1 reinoud
2816 1.1 reinoud /* TODO check if both area's are logically the same */
2817 1.1 reinoud error = 0;
2818 1.1 reinoud if (!error1 && error2) {
2819 1.1 reinoud /* first OK, second faulty */
2820 1.1 reinoud pwarn("Backup volume descriptor missing or damaged\n");
2821 1.1 reinoud if (context.format_flags & FORMAT_SEQUENTIAL) {
2822 1.1 reinoud pwarn("Can't fixup backup volume descriptor on "
2823 1.1 reinoud "SEQUENTIAL media\n");
2824 1.1 reinoud } else if (ask(1, "Fixup backup volume descriptor")) {
2825 1.1 reinoud error = udf_copy_VDS_area(vds2_buf, vds1_buf);
2826 1.1 reinoud pwarn("\n");
2827 1.1 reinoud }
2828 1.1 reinoud }
2829 1.1 reinoud if (error1 && !error2) {
2830 1.1 reinoud /* second OK, first faulty */
2831 1.1 reinoud pwarn("Primary volume descriptor missing or damaged\n");
2832 1.1 reinoud if (context.format_flags & FORMAT_SEQUENTIAL) {
2833 1.1 reinoud pwarn("Can't fix up primary volume descriptor on "
2834 1.1 reinoud "SEQUENTIAL media\n");
2835 1.1 reinoud } else if (ask(1, "Fix up primary volume descriptor")) {
2836 1.1 reinoud error = udf_copy_VDS_area(vds1_buf, vds2_buf);
2837 1.1 reinoud }
2838 1.1 reinoud }
2839 1.1 reinoud if (error)
2840 1.1 reinoud pwarn("copying VDS areas failed!\n");
2841 1.1 reinoud if (!preen)
2842 1.1 reinoud printf("\n");
2843 1.1 reinoud
2844 1.1 reinoud return error;
2845 1.1 reinoud }
2846 1.1 reinoud
2847 1.1 reinoud /* --------------------------------------------------------------------- */
2848 1.1 reinoud
2849 1.1 reinoud static int
2850 1.1 reinoud udf_prepare_writing(void)
2851 1.1 reinoud {
2852 1.1 reinoud union dscrptr *zero_dscr, *dscr;
2853 1.1 reinoud struct mmc_trackinfo ti;
2854 1.1 reinoud uint32_t first_lba, loc;
2855 1.1 reinoud int sector_size = context.sector_size;
2856 1.1 reinoud int error;
2857 1.1 reinoud
2858 1.1 reinoud error = udf_prepare_disc();
2859 1.1 reinoud if (error) {
2860 1.1 reinoud pwarn("*** Preparing disc for writing failed!\n");
2861 1.1 reinoud return error;
2862 1.1 reinoud }
2863 1.1 reinoud
2864 1.1 reinoud /* if we are not on sequential media, we're done */
2865 1.1 reinoud if ((mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) == 0)
2866 1.1 reinoud return 0;
2867 1.1 reinoud assert(context.format_flags & FORMAT_VAT);
2868 1.1 reinoud
2869 1.1 reinoud /* if the disc is full, we drop back to read only */
2870 1.1 reinoud if (mmc_discinfo.disc_state == MMC_STATE_FULL)
2871 1.1 reinoud rdonly = 1;
2872 1.1 reinoud if (rdonly)
2873 1.1 reinoud return 0;
2874 1.1 reinoud
2875 1.1 reinoud /* check if we need to open the last track */
2876 1.1 reinoud ti.tracknr = mmc_discinfo.last_track_last_session;
2877 1.1 reinoud error = udf_update_trackinfo(&ti);
2878 1.1 reinoud if (error)
2879 1.1 reinoud return error;
2880 1.6 riastrad if (!(ti.flags & MMC_TRACKINFO_BLANK) &&
2881 1.1 reinoud (ti.flags & MMC_TRACKINFO_NWA_VALID)) {
2882 1.1 reinoud /*
2883 1.1 reinoud * Not closed; translate next_writable to a position relative to our
2884 1.1 reinoud * backing partition
2885 1.1 reinoud */
2886 1.1 reinoud context.alloc_pos[context.data_part] = ti.next_writable -
2887 1.1 reinoud udf_rw32(context.partitions[context.data_part]->start_loc);
2888 1.1 reinoud wrtrack_skew = ti.next_writable % layout.blockingnr;
2889 1.1 reinoud return 0;
2890 1.1 reinoud }
2891 1.1 reinoud assert(ti.flags & MMC_TRACKINFO_NWA_VALID);
2892 1.1 reinoud
2893 1.1 reinoud /* just in case */
2894 1.1 reinoud udf_suspend_writing();
2895 1.1 reinoud
2896 1.1 reinoud /* 'add' a new track */
2897 1.1 reinoud udf_update_discinfo();
2898 1.1 reinoud memset(&context.last_ti, 0, sizeof(struct mmc_trackinfo));
2899 1.1 reinoud context.last_ti.tracknr = mmc_discinfo.first_track_last_session;
2900 1.1 reinoud (void) udf_update_trackinfo(&context.last_ti);
2901 1.1 reinoud
2902 1.1 reinoud assert(mmc_discinfo.last_session_state == MMC_STATE_EMPTY);
2903 1.1 reinoud first_lba = context.last_ti.track_start;
2904 1.1 reinoud wrtrack_skew = context.last_ti.track_start % layout.blockingnr;
2905 1.1 reinoud
2906 1.1 reinoud /*
2907 1.1 reinoud * location of iso9660 vrs is defined as first sector AFTER 32kb,
2908 1.1 reinoud * minimum `sector size' 2048
2909 1.1 reinoud */
2910 1.1 reinoud layout.iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size)
2911 1.1 reinoud + first_lba;
2912 1.1 reinoud
2913 1.1 reinoud /* anchor starts at specified offset in sectors */
2914 1.1 reinoud layout.anchors[0] = first_lba + 256;
2915 1.1 reinoud
2916 1.1 reinoud /* ready for appending, write preamble, we are using overwrite here! */
2917 1.1 reinoud if ((zero_dscr = calloc(1, context.sector_size)) == NULL)
2918 1.1 reinoud return ENOMEM;
2919 1.1 reinoud loc = first_lba;
2920 1.1 reinoud for (; loc < first_lba + 256; loc++) {
2921 1.1 reinoud if ((error = udf_write_sector(zero_dscr, loc))) {
2922 1.1 reinoud free(zero_dscr);
2923 1.1 reinoud return error;
2924 1.1 reinoud }
2925 1.1 reinoud }
2926 1.1 reinoud free(zero_dscr);
2927 1.1 reinoud
2928 1.1 reinoud /* write new ISO9660 volume recognition sequence */
2929 1.1 reinoud if ((error = udf_write_iso9660_vrs())) {
2930 1.1 reinoud pwarn("internal error: can't write iso966 VRS in new session!\n");
2931 1.1 reinoud rdonly = 1;
2932 1.1 reinoud return error;
2933 1.1 reinoud }
2934 1.1 reinoud
2935 1.1 reinoud /* write out our old anchor, VDS spaces will be reused */
2936 1.1 reinoud assert(context.anchors[0]);
2937 1.1 reinoud dscr = (union dscrptr *) context.anchors[0];
2938 1.1 reinoud loc = layout.anchors[0];
2939 1.1 reinoud if ((error = udf_write_dscr_phys(dscr, loc, 1))) {
2940 1.1 reinoud pwarn("internal error: can't write anchor in new session!\n");
2941 1.1 reinoud rdonly = 1;
2942 1.1 reinoud return error;
2943 1.1 reinoud }
2944 1.1 reinoud
2945 1.1 reinoud context.alloc_pos[context.data_part] = first_lba + 257 -
2946 1.1 reinoud udf_rw32(context.partitions[context.data_part]->start_loc);
2947 1.1 reinoud
2948 1.1 reinoud return 0;
2949 1.1 reinoud }
2950 1.1 reinoud
2951 1.1 reinoud
2952 1.1 reinoud static int
2953 1.1 reinoud udf_close_volume_vat(void)
2954 1.1 reinoud {
2955 1.1 reinoud int integrity_type;
2956 1.1 reinoud
2957 1.1 reinoud /* only write out when its open */
2958 1.1 reinoud integrity_type = udf_rw32(context.logvol_integrity->integrity_type);
2959 1.1 reinoud if (integrity_type == UDF_INTEGRITY_CLOSED)
2960 1.1 reinoud return 0;
2961 1.1 reinoud
2962 1.1 reinoud if (!preen)
2963 1.1 reinoud printf("\n");
2964 1.1 reinoud if (!ask(1, "Write out modifications"))
2965 1.1 reinoud return 0;
2966 1.1 reinoud
2967 1.1 reinoud /* writeout our VAT contents */
2968 1.1 reinoud udf_allow_writing();
2969 1.1 reinoud return udf_writeout_VAT();
2970 1.1 reinoud }
2971 1.1 reinoud
2972 1.1 reinoud
2973 1.1 reinoud static int
2974 1.1 reinoud udf_close_volume(void)
2975 1.1 reinoud {
2976 1.1 reinoud struct part_desc *part;
2977 1.1 reinoud struct part_hdr_desc *phd;
2978 1.1 reinoud struct logvol_int_desc *lvid;
2979 1.1 reinoud struct udf_logvol_info *lvinfo;
2980 1.1 reinoud struct logvol_desc *logvol;
2981 1.1 reinoud uint32_t bitmap_len, bitmap_lb, bitmap_numlb;
2982 1.1 reinoud int i, equal, error;
2983 1.1 reinoud
2984 1.1 reinoud lvid = context.logvol_integrity;
2985 1.1 reinoud logvol = context.logical_vol;
2986 1.1 reinoud lvinfo = context.logvol_info;
2987 1.1 reinoud assert(lvid);
2988 1.1 reinoud assert(logvol);
2989 1.1 reinoud assert(lvinfo);
2990 1.1 reinoud
2991 1.1 reinoud /* check our highest unique id */
2992 1.1 reinoud if (context.unique_id > udf_rw64(lvid->lvint_next_unique_id)) {
2993 1.3 martin pwarn("Last unique id updated from %" PRIi64 " to %" PRIi64 " : FIXED\n",
2994 1.1 reinoud udf_rw64(lvid->lvint_next_unique_id),
2995 1.1 reinoud context.unique_id);
2996 1.1 reinoud open_integrity = 1;
2997 1.1 reinoud }
2998 1.1 reinoud
2999 1.1 reinoud /* check file/directory counts */
3000 1.1 reinoud if (context.num_files != udf_rw32(lvinfo->num_files)) {
3001 1.1 reinoud pwarn("Number of files corrected from %d to %d : FIXED\n",
3002 1.1 reinoud udf_rw32(lvinfo->num_files),
3003 1.1 reinoud context.num_files);
3004 1.1 reinoud open_integrity = 1;
3005 1.1 reinoud }
3006 1.1 reinoud if (context.num_directories != udf_rw32(lvinfo->num_directories)) {
3007 1.1 reinoud pwarn("Number of directories corrected from %d to %d : FIXED\n",
3008 1.1 reinoud udf_rw32(lvinfo->num_directories),
3009 1.1 reinoud context.num_directories);
3010 1.1 reinoud open_integrity = 1;
3011 1.1 reinoud }
3012 1.1 reinoud
3013 1.1 reinoud if (vat_writeout)
3014 1.1 reinoud open_integrity = 1;
3015 1.1 reinoud
3016 1.1 reinoud if (open_integrity)
3017 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_OPEN);
3018 1.1 reinoud
3019 1.1 reinoud if (context.format_flags & FORMAT_VAT)
3020 1.1 reinoud return udf_close_volume_vat();
3021 1.1 reinoud
3022 1.1 reinoud /* adjust free space accounting! */
3023 1.1 reinoud for (i = 0; i < UDF_PARTITIONS; i++) {
3024 1.1 reinoud part = context.partitions[i];
3025 1.1 reinoud if (!part)
3026 1.1 reinoud continue;
3027 1.1 reinoud phd = &part->pd_part_hdr;
3028 1.1 reinoud bitmap_len = udf_rw32(phd->unalloc_space_bitmap.len);
3029 1.1 reinoud bitmap_lb = udf_rw32(phd->unalloc_space_bitmap.lb_num);
3030 1.1 reinoud
3031 1.1 reinoud if (bitmap_len == 0) {
3032 1.1 reinoud error = 0;
3033 1.1 reinoud continue;
3034 1.1 reinoud }
3035 1.1 reinoud
3036 1.1 reinoud equal = memcmp( recorded_part_unalloc_bits[i],
3037 1.1 reinoud context.part_unalloc_bits[i],
3038 1.1 reinoud bitmap_len) == 0;
3039 1.1 reinoud
3040 1.1 reinoud if (!equal || (context.part_free[i] != recorded_part_free[i])) {
3041 1.1 reinoud if (!equal)
3042 1.1 reinoud pwarn("Calculated bitmap for partition %d not equal "
3043 1.1 reinoud "to recorded one : FIXED\n", i);
3044 1.1 reinoud pwarn("Free space on partition %d corrected "
3045 1.1 reinoud "from %d to %d blocks : FIXED\n", i,
3046 1.1 reinoud recorded_part_free[i],
3047 1.1 reinoud context.part_free[i]);
3048 1.1 reinoud
3049 1.1 reinoud /* write out updated free space map */
3050 1.1 reinoud pwarn("Updating unallocated bitmap for partition\n");
3051 1.1 reinoud if (!preen)
3052 1.1 reinoud printf("Writing free space map "
3053 1.1 reinoud "for partition %d\n", i);
3054 1.1 reinoud error = 0;
3055 1.1 reinoud if (context.vtop_tp[i] == UDF_VTOP_TYPE_META) {
3056 1.1 reinoud if (context.meta_bitmap) {
3057 1.1 reinoud assert(i == context.metadata_part);
3058 1.1 reinoud error = udf_process_file(
3059 1.1 reinoud (union dscrptr *) context.meta_bitmap,
3060 1.1 reinoud context.data_part,
3061 1.1 reinoud (uint8_t **) &(context.part_unalloc_bits[i]),
3062 1.1 reinoud AD_SAVE_FILE, NULL);
3063 1.1 reinoud }
3064 1.1 reinoud } else {
3065 1.1 reinoud bitmap_numlb = udf_bytes_to_sectors(bitmap_len);
3066 1.1 reinoud error = udf_write_dscr_virt(
3067 1.1 reinoud (union dscrptr *) context.part_unalloc_bits[i],
3068 1.1 reinoud bitmap_lb,
3069 1.1 reinoud i,
3070 1.1 reinoud bitmap_numlb);
3071 1.1 reinoud }
3072 1.1 reinoud if (error)
3073 1.1 reinoud pwarn("Updating unallocated bitmap failed, "
3074 1.1 reinoud "continuing\n");
3075 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_OPEN);
3076 1.1 reinoud }
3077 1.1 reinoud }
3078 1.1 reinoud
3079 1.1 reinoud /* write out the logical volume integrity sequence */
3080 1.1 reinoud error = udf_writeout_lvint();
3081 1.1 reinoud
3082 1.1 reinoud return error;
3083 1.1 reinoud }
3084 1.1 reinoud
3085 1.1 reinoud /* --------------------------------------------------------------------- */
3086 1.1 reinoud
3087 1.1 reinoud /*
3088 1.1 reinoud * Main part of file system checking.
3089 1.1 reinoud *
3090 1.1 reinoud * Walk the entire directory tree and check all link counts and rebuild the
3091 1.1 reinoud * free space map (if present) on the go.
3092 1.1 reinoud */
3093 1.1 reinoud
3094 1.1 reinoud static struct udf_fsck_node *
3095 1.1 reinoud udf_new_fsck_node(struct udf_fsck_node *parent, struct long_ad *loc, char *fname)
3096 1.1 reinoud {
3097 1.1 reinoud struct udf_fsck_node *this;
3098 1.1 reinoud this = calloc(1, sizeof(struct udf_fsck_node));
3099 1.1 reinoud if (!this)
3100 1.1 reinoud return NULL;
3101 1.1 reinoud
3102 1.1 reinoud this->parent = parent;
3103 1.1 reinoud this->fname = strdup(fname);
3104 1.1 reinoud this->loc = *loc;
3105 1.1 reinoud this->fsck_flags = 0;
3106 1.1 reinoud
3107 1.1 reinoud this->link_count = 0;
3108 1.1 reinoud this->found_link_count = 0;
3109 1.1 reinoud
3110 1.1 reinoud return this;
3111 1.1 reinoud }
3112 1.1 reinoud
3113 1.1 reinoud
3114 1.1 reinoud static void
3115 1.1 reinoud udf_node_path_piece(char *pathname, struct udf_fsck_node *node)
3116 1.1 reinoud {
3117 1.1 reinoud if (node->parent) {
3118 1.1 reinoud udf_node_path_piece(pathname, node->parent);
3119 1.1 reinoud if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR)
3120 1.1 reinoud strcat(pathname, "");
3121 1.1 reinoud else
3122 1.1 reinoud strcat(pathname, "/");
3123 1.1 reinoud }
3124 1.1 reinoud strcat(pathname, node->fname);
3125 1.1 reinoud }
3126 1.1 reinoud
3127 1.1 reinoud
3128 1.1 reinoud static char *
3129 1.1 reinoud udf_node_path(struct udf_fsck_node *node)
3130 1.1 reinoud {
3131 1.1 reinoud static char pathname[MAXPATHLEN + 10];
3132 1.1 reinoud
3133 1.1 reinoud strcpy(pathname, "`");
3134 1.1 reinoud if (node->parent)
3135 1.1 reinoud udf_node_path_piece(pathname, node);
3136 1.1 reinoud else
3137 1.1 reinoud strcat(pathname, "/");
3138 1.1 reinoud strcat(pathname, "'");
3139 1.1 reinoud
3140 1.1 reinoud return pathname;
3141 1.1 reinoud }
3142 1.1 reinoud
3143 1.1 reinoud
3144 1.1 reinoud static void
3145 1.1 reinoud udf_recursive_keep(struct udf_fsck_node *node)
3146 1.1 reinoud {
3147 1.1 reinoud while (node->parent) {
3148 1.1 reinoud node = node->parent;
3149 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_KEEP;
3150 1.1 reinoud }
3151 1.1 reinoud }
3152 1.1 reinoud
3153 1.1 reinoud
3154 1.1 reinoud static int
3155 1.1 reinoud udf_quick_check_fids(struct udf_fsck_node *node, union dscrptr *dscr)
3156 1.1 reinoud {
3157 1.1 reinoud struct udf_fsck_fid_context fid_context;
3158 1.1 reinoud int error;
3159 1.1 reinoud
3160 1.1 reinoud fid_context.fid_offset = 0;
3161 1.1 reinoud fid_context.data_left = node->found.inf_len;
3162 1.1 reinoud error = udf_process_file(dscr, context.fids_part,
3163 1.1 reinoud &node->directory,
3164 1.1 reinoud AD_CHECK_FIDS,
3165 1.1 reinoud &fid_context);
3166 1.1 reinoud
3167 1.1 reinoud return error;
3168 1.1 reinoud }
3169 1.1 reinoud
3170 1.1 reinoud
3171 1.1 reinoud /* read descriptor at node's location */
3172 1.1 reinoud static int
3173 1.1 reinoud udf_read_node_dscr(struct udf_fsck_node *node, union dscrptr **dscrptr)
3174 1.1 reinoud {
3175 1.1 reinoud *dscrptr = NULL;
3176 1.1 reinoud return udf_read_dscr_virt(
3177 1.1 reinoud udf_rw32(node->loc.loc.lb_num),
3178 1.1 reinoud udf_rw16(node->loc.loc.part_num),
3179 1.1 reinoud dscrptr);
3180 1.1 reinoud }
3181 1.1 reinoud
3182 1.1 reinoud
3183 1.1 reinoud static int
3184 1.1 reinoud udf_extract_node_info(struct udf_fsck_node *node, union dscrptr *dscr,
3185 1.1 reinoud int be_quiet)
3186 1.1 reinoud {
3187 1.1 reinoud struct icb_tag *icb = NULL;
3188 1.1 reinoud struct file_entry *fe = NULL;
3189 1.1 reinoud struct extfile_entry *efe = NULL;
3190 1.1 reinoud int ad_type, error;
3191 1.1 reinoud
3192 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
3193 1.1 reinoud fe = (struct file_entry *) dscr;
3194 1.1 reinoud icb = &fe->icbtag;
3195 1.1 reinoud node->declared.inf_len = udf_rw64(fe->inf_len);
3196 1.1 reinoud node->declared.obj_size = udf_rw64(fe->inf_len);
3197 1.1 reinoud node->declared.logblks_rec = udf_rw64(fe->logblks_rec);
3198 1.1 reinoud node->link_count = udf_rw16(fe->link_cnt);
3199 1.1 reinoud node->unique_id = udf_rw64(fe->unique_id);
3200 1.1 reinoud
3201 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */
3202 1.1 reinoud //if (fe->unique_id == 33) { return ENOENT;}
3203 1.1 reinoud
3204 1.1 reinoud }
3205 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
3206 1.1 reinoud efe = (struct extfile_entry *) dscr;
3207 1.1 reinoud icb = &efe->icbtag;
3208 1.1 reinoud node->declared.inf_len = udf_rw64(efe->inf_len);
3209 1.1 reinoud node->declared.obj_size = udf_rw64(efe->obj_size);
3210 1.1 reinoud node->declared.logblks_rec = udf_rw64(efe->logblks_rec);
3211 1.1 reinoud node->link_count = udf_rw16(efe->link_cnt);
3212 1.1 reinoud node->unique_id = udf_rw64(efe->unique_id);
3213 1.1 reinoud node->streamdir_loc = efe->streamdir_icb;
3214 1.1 reinoud if (node->streamdir_loc.len)
3215 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_HAS_STREAM_DIR;
3216 1.1 reinoud
3217 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */
3218 1.1 reinoud //if (efe->unique_id == 0x891) { return ENOENT;}
3219 1.1 reinoud
3220 1.1 reinoud }
3221 1.1 reinoud
3222 1.1 reinoud if (!fe && !efe) {
3223 1.1 reinoud //printf("NOT REFERENCING AN FE/EFE!\n");
3224 1.1 reinoud return ENOENT;
3225 1.1 reinoud }
3226 1.1 reinoud
3227 1.1 reinoud if (node->unique_id >= context.unique_id)
3228 1.1 reinoud context.unique_id = node->unique_id+1;
3229 1.1 reinoud
3230 1.1 reinoud ad_type = udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
3231 1.1 reinoud if ((ad_type != UDF_ICB_INTERN_ALLOC) &&
3232 1.1 reinoud (ad_type != UDF_ICB_SHORT_ALLOC) &&
3233 1.1 reinoud (ad_type != UDF_ICB_LONG_ALLOC)) {
3234 1.1 reinoud pwarn("%s : unknown allocation type\n",
3235 1.1 reinoud udf_node_path(node));
3236 1.1 reinoud return EINVAL;
3237 1.1 reinoud }
3238 1.1 reinoud
3239 1.1 reinoud bzero(&node->found, sizeof(node->found));
3240 1.1 reinoud error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL,
3241 1.1 reinoud AD_GATHER_STATS, (void *) &node->found);
3242 1.1 reinoud
3243 1.1 reinoud switch (icb->file_type) {
3244 1.1 reinoud case UDF_ICB_FILETYPE_RANDOMACCESS :
3245 1.1 reinoud case UDF_ICB_FILETYPE_BLOCKDEVICE :
3246 1.1 reinoud case UDF_ICB_FILETYPE_CHARDEVICE :
3247 1.1 reinoud case UDF_ICB_FILETYPE_FIFO :
3248 1.1 reinoud case UDF_ICB_FILETYPE_SOCKET :
3249 1.1 reinoud case UDF_ICB_FILETYPE_SYMLINK :
3250 1.1 reinoud case UDF_ICB_FILETYPE_REALTIME :
3251 1.1 reinoud break;
3252 1.1 reinoud default:
3253 1.1 reinoud /* unknown or unsupported file type, TODO clearing? */
3254 1.1 reinoud free(dscr);
3255 1.1 reinoud pwarn("%s : specification violation, unknown file type %d\n",
3256 1.1 reinoud udf_node_path(node), icb->file_type);
3257 1.1 reinoud return ENOENT;
3258 1.1 reinoud case UDF_ICB_FILETYPE_STREAMDIR :
3259 1.1 reinoud case UDF_ICB_FILETYPE_DIRECTORY :
3260 1.1 reinoud /* read in the directory contents */
3261 1.1 reinoud error = udf_readin_file(dscr, udf_rw16(node->loc.loc.part_num),
3262 1.1 reinoud &node->directory, NULL);
3263 1.1 reinoud
3264 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */
3265 1.1 reinoud //if (dscr->efe.unique_id == 109) node->directory[125] = 0xff;
3266 1.1 reinoud //if (dscr->efe.unique_id == 310) memset(node->directory+1024, 0, 300);
3267 1.1 reinoud
3268 1.1 reinoud if (error && !be_quiet) {
3269 1.1 reinoud pwarn("%s : directory has read errors\n",
3270 1.1 reinoud udf_node_path(node));
3271 1.1 reinoud if (ask(0, "Directory could be fixed or cleared. "
3272 1.1 reinoud "Wipe defective directory")) {
3273 1.1 reinoud return ENOENT;
3274 1.1 reinoud }
3275 1.1 reinoud udf_recursive_keep(node);
3276 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3277 1.1 reinoud }
3278 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_DIRECTORY;
3279 1.1 reinoud error = udf_quick_check_fids(node, dscr);
3280 1.1 reinoud if (error) {
3281 1.1 reinoud if (!(node->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR))
3282 1.1 reinoud pwarn("%s : directory file entries need repair\n",
3283 1.1 reinoud udf_node_path(node));
3284 1.1 reinoud udf_recursive_keep(node);
3285 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3286 1.1 reinoud }
3287 1.1 reinoud }
3288 1.1 reinoud
3289 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */
3290 1.1 reinoud //if (fe->unique_id == 0) node->link_count++;
3291 1.1 reinoud //if (efe->unique_id == 0) node->link_count++;
3292 1.1 reinoud //if (efe->unique_id == 772) { node->declared.inf_len += 205; node->declared.obj_size -= 0; }
3293 1.1 reinoud
3294 1.1 reinoud return 0;
3295 1.1 reinoud }
3296 1.1 reinoud
3297 1.1 reinoud
3298 1.1 reinoud static void
3299 1.1 reinoud udf_fixup_lengths_pass1(struct udf_fsck_node *node, union dscrptr *dscr)
3300 1.1 reinoud {
3301 1.1 reinoud int64_t diff;
3302 1.1 reinoud
3303 1.1 reinoud /* file length check */
3304 1.1 reinoud diff = node->found.inf_len - node->declared.inf_len;
3305 1.1 reinoud if (diff) {
3306 1.1 reinoud pwarn("%s : recorded information length incorrect: "
3307 1.3 martin "%" PRIu64 " instead of declared %" PRIu64 "\n",
3308 1.1 reinoud udf_node_path(node),
3309 1.1 reinoud node->found.inf_len, node->declared.inf_len);
3310 1.1 reinoud node->declared.inf_len = node->found.inf_len;
3311 1.1 reinoud udf_recursive_keep(node);
3312 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3313 1.1 reinoud }
3314 1.1 reinoud
3315 1.1 reinoud /* recorded logical blocks count check */
3316 1.1 reinoud diff = node->found.logblks_rec - node->declared.logblks_rec;
3317 1.1 reinoud if (diff) {
3318 1.1 reinoud pwarn("%s : logical blocks recorded incorrect: "
3319 1.3 martin "%" PRIu64 " instead of declared %" PRIu64 ", fixing\n",
3320 1.1 reinoud udf_node_path(node),
3321 1.1 reinoud node->found.logblks_rec, node->declared.logblks_rec);
3322 1.1 reinoud node->declared.logblks_rec = node->found.logblks_rec;
3323 1.1 reinoud udf_recursive_keep(node);
3324 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3325 1.1 reinoud }
3326 1.1 reinoud
3327 1.1 reinoud /* tally object sizes for streamdirs */
3328 1.1 reinoud node->found.obj_size = node->found.inf_len;
3329 1.1 reinoud if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_ENTRY) {
3330 1.1 reinoud assert(node->parent); /* streamdir itself */
3331 1.1 reinoud if (node->parent->parent)
3332 1.1 reinoud node->parent->parent->found.obj_size +=
3333 1.1 reinoud node->found.inf_len;
3334 1.1 reinoud }
3335 1.1 reinoud
3336 1.1 reinoud /* check descriptor CRC length */
3337 1.1 reinoud if (udf_rw16(dscr->tag.desc_crc_len) !=
3338 1.1 reinoud udf_tagsize(dscr, 1) - sizeof(struct desc_tag)) {
3339 1.1 reinoud pwarn("%s : node file descriptor CRC length mismatch; "
3340 1.3 martin "%d declared, %zu\n",
3341 1.1 reinoud udf_node_path(node), udf_rw16(dscr->tag.desc_crc_len),
3342 1.1 reinoud udf_tagsize(dscr, 1) - sizeof(struct desc_tag));
3343 1.1 reinoud udf_recursive_keep(node);
3344 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3345 1.1 reinoud }
3346 1.1 reinoud }
3347 1.1 reinoud
3348 1.1 reinoud
3349 1.1 reinoud static void
3350 1.1 reinoud udf_node_pass1_add_entry(struct udf_fsck_node *node,
3351 1.1 reinoud struct fileid_desc *fid, struct dirent *dirent)
3352 1.1 reinoud {
3353 1.1 reinoud struct udf_fsck_node *leaf_node;
3354 1.1 reinoud int entry;
3355 1.1 reinoud
3356 1.1 reinoud /* skip deleted FID entries */
3357 1.1 reinoud if (fid->file_char & UDF_FILE_CHAR_DEL)
3358 1.1 reinoud return;
3359 1.1 reinoud
3360 1.1 reinoud if (udf_rw32(fid->icb.loc.lb_num) == 0) {
3361 1.1 reinoud pwarn("%s : FileID entry `%s` has invalid location\n",
3362 1.1 reinoud udf_node_path(node), dirent->d_name);
3363 1.1 reinoud udf_recursive_keep(node);
3364 1.1 reinoud if (node->parent)
3365 1.1 reinoud node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3366 1.1 reinoud return;
3367 1.1 reinoud }
3368 1.1 reinoud
3369 1.1 reinoud /* increase parent link count */
3370 1.1 reinoud if (fid->file_char & UDF_FILE_CHAR_PAR) {
3371 1.1 reinoud if (node->parent)
3372 1.1 reinoud node->parent->found_link_count++;
3373 1.1 reinoud return;
3374 1.1 reinoud }
3375 1.1 reinoud
3376 1.1 reinoud /* lookup if we already know this node */
3377 1.1 reinoud leaf_node = udf_node_lookup(&fid->icb);
3378 1.1 reinoud if (leaf_node) {
3379 1.1 reinoud /* got a hard link! */
3380 1.1 reinoud leaf_node->found_link_count++;
3381 1.1 reinoud return;
3382 1.1 reinoud }
3383 1.1 reinoud
3384 1.1 reinoud /* create new node */
3385 1.1 reinoud leaf_node = udf_new_fsck_node(
3386 1.1 reinoud node, &fid->icb, dirent->d_name);
3387 1.1 reinoud if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR)
3388 1.1 reinoud leaf_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_ENTRY;
3389 1.1 reinoud
3390 1.1 reinoud TAILQ_INSERT_TAIL(&fs_nodes, leaf_node, next);
3391 1.1 reinoud entry = udf_calc_node_hash(&fid->icb);
3392 1.1 reinoud LIST_INSERT_HEAD(&fs_nodes_hash[entry], leaf_node, next_hash);
3393 1.1 reinoud }
3394 1.1 reinoud
3395 1.1 reinoud
3396 1.1 reinoud static void
3397 1.1 reinoud udf_node_pass1_add_streamdir_entry(struct udf_fsck_node *node)
3398 1.1 reinoud {
3399 1.1 reinoud struct udf_fsck_node *leaf_node;
3400 1.1 reinoud int entry;
3401 1.1 reinoud
3402 1.1 reinoud /* check for recursion */
3403 1.1 reinoud if (node->fsck_flags & FSCK_NODE_FLAG_STREAM) {
3404 1.1 reinoud /* recursive streams are not allowed by spec */
3405 1.1 reinoud pwarn("%s : specification violation, recursive stream dir\n",
3406 1.1 reinoud udf_node_path(node));
3407 1.1 reinoud udf_recursive_keep(node);
3408 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_WIPE_STREAM_DIR;
3409 1.1 reinoud return;
3410 1.1 reinoud }
3411 1.1 reinoud
3412 1.1 reinoud /* lookup if we already know this node */
3413 1.1 reinoud leaf_node = udf_node_lookup(&node->streamdir_loc);
3414 1.1 reinoud if (leaf_node) {
3415 1.1 reinoud pwarn("%s : specification violation, hardlinked streamdir\n",
3416 1.1 reinoud udf_node_path(leaf_node));
3417 1.1 reinoud udf_recursive_keep(node);
3418 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_WIPE_STREAM_DIR;
3419 1.1 reinoud return;
3420 1.1 reinoud }
3421 1.1 reinoud
3422 1.1 reinoud /* create new node */
3423 1.1 reinoud leaf_node = udf_new_fsck_node(
3424 1.1 reinoud node, &node->streamdir_loc, strdup(""));
3425 1.1 reinoud leaf_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_DIR;
3426 1.1 reinoud
3427 1.1 reinoud /* streamdirs have link count 0 : ECMA 4/14.9.6 */
3428 1.1 reinoud leaf_node->found_link_count--;
3429 1.1 reinoud
3430 1.1 reinoud /* insert in to lists */
3431 1.1 reinoud TAILQ_INSERT_TAIL(&fs_nodes, leaf_node, next);
3432 1.1 reinoud entry = udf_calc_node_hash(&node->streamdir_loc);
3433 1.1 reinoud LIST_INSERT_HEAD(&fs_nodes_hash[entry], leaf_node, next_hash);
3434 1.1 reinoud }
3435 1.1 reinoud
3436 1.1 reinoud
3437 1.1 reinoud static int
3438 1.1 reinoud udf_process_node_pass1(struct udf_fsck_node *node, union dscrptr *dscr)
3439 1.1 reinoud {
3440 1.1 reinoud struct fileid_desc *fid;
3441 1.1 reinoud struct dirent dirent;
3442 1.1 reinoud struct charspec osta_charspec;
3443 1.1 reinoud int64_t fpos, new_length, rest_len;
3444 1.1 reinoud uint32_t fid_len;
3445 1.1 reinoud uint8_t *bpos;
3446 1.1 reinoud int isdir;
3447 1.1 reinoud int error;
3448 1.1 reinoud
3449 1.1 reinoud isdir = node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY;
3450 1.1 reinoud
3451 1.1 reinoud /* keep link count */
3452 1.1 reinoud node->found_link_count++;
3453 1.1 reinoud
3454 1.1 reinoud if (isdir) {
3455 1.1 reinoud assert(node->directory);
3456 1.1 reinoud udf_rebuild_fid_stream(node, &new_length);
3457 1.1 reinoud node->found.inf_len = new_length;
3458 1.1 reinoud rest_len = new_length;
3459 1.1 reinoud }
3460 1.1 reinoud
3461 1.1 reinoud udf_fixup_lengths_pass1(node, dscr);
3462 1.1 reinoud
3463 1.1 reinoud /* check UniqueID */
3464 1.1 reinoud if (node->parent) {
3465 1.1 reinoud if (node->fsck_flags & FSCK_NODE_FLAG_STREAM) {
3466 1.1 reinoud
3467 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */
3468 1.1 reinoud //node->unique_id = 0xdeadbeefcafe;
3469 1.1 reinoud
3470 1.1 reinoud if (node->unique_id != node->parent->unique_id) {
3471 1.1 reinoud pwarn("%s : stream file/dir UniqueID mismatch "
3472 1.1 reinoud "with parent\n",
3473 1.1 reinoud udf_node_path(node));
3474 1.1 reinoud /* do the work here prematurely for our siblings */
3475 1.1 reinoud udf_recursive_keep(node);
3476 1.1 reinoud node->unique_id = node->parent->unique_id;
3477 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_COPY_PARENT_ID |
3478 1.1 reinoud FSCK_NODE_FLAG_DIRTY;
3479 1.1 reinoud assert(node->parent);
3480 1.1 reinoud node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3481 1.1 reinoud }
3482 1.1 reinoud } else if (node->unique_id < 16) {
3483 1.1 reinoud pwarn("%s : file has bad UniqueID\n",
3484 1.1 reinoud udf_node_path(node));
3485 1.1 reinoud udf_recursive_keep(node);
3486 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_NEW_UNIQUE_ID;
3487 1.1 reinoud assert(node->parent);
3488 1.1 reinoud node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3489 1.1 reinoud }
3490 1.1 reinoud } else {
3491 1.1 reinoud /* rootdir */
3492 1.1 reinoud if (node->unique_id != 0) {
3493 1.1 reinoud pwarn("%s : has bad UniqueID, has to be zero\n",
3494 1.1 reinoud udf_node_path(node));
3495 1.1 reinoud udf_recursive_keep(node);
3496 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3497 1.1 reinoud }
3498 1.1 reinoud }
3499 1.1 reinoud
3500 1.1 reinoud /* add streamdir if present */
3501 1.1 reinoud if (node->fsck_flags & FSCK_NODE_FLAG_HAS_STREAM_DIR)
3502 1.1 reinoud udf_node_pass1_add_streamdir_entry(node);
3503 1.1 reinoud
3504 1.1 reinoud /* add all children */
3505 1.1 reinoud if (isdir) {
3506 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_PAR_NOT_FOUND;
3507 1.1 reinoud rest_len = node->found.inf_len;
3508 1.1 reinoud
3509 1.2 wiz /* walk through all our FIDs in the directory stream */
3510 1.1 reinoud bpos = node->directory;
3511 1.1 reinoud fpos = 0;
3512 1.1 reinoud while (rest_len > 0) {
3513 1.1 reinoud fid = (struct fileid_desc *) bpos;
3514 1.1 reinoud fid_len = udf_fidsize(fid);
3515 1.1 reinoud
3516 1.1 reinoud /* get printable name */
3517 1.1 reinoud memset(&dirent, 0, sizeof(dirent));
3518 1.1 reinoud udf_osta_charset(&osta_charspec);
3519 1.1 reinoud udf_to_unix_name(dirent.d_name, NAME_MAX,
3520 1.1 reinoud (char *) fid->data + udf_rw16(fid->l_iu), fid->l_fi,
3521 1.1 reinoud &osta_charspec);
3522 1.1 reinoud dirent.d_namlen = strlen(dirent.d_name);
3523 1.1 reinoud
3524 1.1 reinoud /* '..' has no name, so provide one */
3525 1.1 reinoud if (fid->file_char & UDF_FILE_CHAR_PAR) {
3526 1.1 reinoud strcpy(dirent.d_name, "..");
3527 1.1 reinoud node->fsck_flags &= ~FSCK_NODE_FLAG_PAR_NOT_FOUND;
3528 1.1 reinoud }
3529 1.1 reinoud
3530 1.1 reinoud udf_node_pass1_add_entry(node, fid, &dirent);
3531 1.1 reinoud
3532 1.1 reinoud fpos += fid_len;
3533 1.1 reinoud bpos += fid_len;
3534 1.1 reinoud rest_len -= fid_len;
3535 1.1 reinoud }
3536 1.1 reinoud }
3537 1.1 reinoud
3538 1.1 reinoud error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL,
3539 1.1 reinoud AD_CHECK_USED, node);
3540 1.1 reinoud if (error) {
3541 1.1 reinoud pwarn("%s : internal error: checking for being allocated shouldn't fail\n",
3542 1.1 reinoud udf_node_path(node));
3543 1.1 reinoud return EINVAL;
3544 1.1 reinoud }
3545 1.1 reinoud /* file/directory is OK and referenced as its size won't change */
3546 1.1 reinoud error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL,
3547 1.1 reinoud AD_MARK_AS_USED, NULL);
3548 1.1 reinoud if (error) {
3549 1.1 reinoud pwarn("%s : internal error: marking allocated shouldn't fail\n",
3550 1.1 reinoud udf_node_path(node));
3551 1.1 reinoud return EINVAL;
3552 1.1 reinoud }
3553 1.7 reinoud (void) fpos;
3554 1.1 reinoud return 0;
3555 1.1 reinoud }
3556 1.1 reinoud
3557 1.1 reinoud
3558 1.1 reinoud static void
3559 1.1 reinoud udf_node_pass3_repairdir(struct udf_fsck_node *node, union dscrptr *dscr)
3560 1.1 reinoud {
3561 1.1 reinoud struct fileid_desc *fid, *last_empty_fid;
3562 1.1 reinoud struct udf_fsck_node *file_node;
3563 1.1 reinoud struct udf_fsck_fid_context fid_context;
3564 1.1 reinoud struct dirent dirent;
3565 1.1 reinoud struct charspec osta_charspec;
3566 1.1 reinoud int64_t fpos, rest_len;
3567 1.1 reinoud uint32_t fid_len;
3568 1.1 reinoud uint8_t *bpos;
3569 1.1 reinoud int parent_missing;
3570 1.1 reinoud int error;
3571 1.1 reinoud
3572 1.1 reinoud pwarn("%s : fixing up directory\n", udf_node_path(node));
3573 1.1 reinoud assert(node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY);
3574 1.1 reinoud
3575 1.1 reinoud rest_len = node->found.inf_len;
3576 1.1 reinoud
3577 1.1 reinoud udf_osta_charset(&osta_charspec);
3578 1.1 reinoud bpos = node->directory;
3579 1.1 reinoud fpos = 0;
3580 1.1 reinoud parent_missing = (node->fsck_flags & FSCK_NODE_FLAG_PAR_NOT_FOUND)? 1:0;
3581 1.1 reinoud
3582 1.1 reinoud last_empty_fid = NULL;
3583 1.1 reinoud while (rest_len > 0) {
3584 1.1 reinoud fid = (struct fileid_desc *) bpos;
3585 1.1 reinoud fid_len = udf_fidsize(fid);
3586 1.1 reinoud
3587 1.1 reinoud /* get printable name */
3588 1.1 reinoud memset(&dirent, 0, sizeof(dirent));
3589 1.1 reinoud udf_to_unix_name(dirent.d_name, NAME_MAX,
3590 1.1 reinoud (char *) fid->data + udf_rw16(fid->l_iu), fid->l_fi,
3591 1.1 reinoud &osta_charspec);
3592 1.1 reinoud dirent.d_namlen = strlen(dirent.d_name);
3593 1.1 reinoud
3594 1.1 reinoud /* '..' has no name, so provide one */
3595 1.1 reinoud if (fid->file_char & UDF_FILE_CHAR_PAR) {
3596 1.1 reinoud strcpy(dirent.d_name, "..");
3597 1.1 reinoud }
3598 1.1 reinoud
3599 1.1 reinoud /* only look up when not deleted */
3600 1.1 reinoud file_node = NULL;
3601 1.1 reinoud if ((fid->file_char & UDF_FILE_CHAR_DEL) == 0)
3602 1.1 reinoud file_node = udf_node_lookup(&fid->icb);
3603 1.1 reinoud
3604 1.1 reinoud /* if found */
3605 1.1 reinoud if (file_node) {
3606 1.1 reinoud /* delete files which couldn't be found */
3607 1.1 reinoud if (file_node && (file_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)) {
3608 1.1 reinoud fid->file_char |= UDF_FILE_CHAR_DEL;
3609 1.1 reinoud memset(&fid->icb, 0, sizeof(struct long_ad));
3610 1.1 reinoud }
3611 1.1 reinoud
3612 1.1 reinoud /* fix up FID UniqueID errors */
3613 1.1 reinoud if (fid->icb.longad_uniqueid != file_node->unique_id)
3614 1.1 reinoud fid->icb.longad_uniqueid = udf_rw64(file_node->unique_id);
3615 1.1 reinoud } else {
3616 1.1 reinoud /* just mark it deleted if not found */
3617 1.1 reinoud fid->file_char |= UDF_FILE_CHAR_DEL;
3618 1.1 reinoud }
3619 1.1 reinoud
3620 1.1 reinoud if (fid->file_char & UDF_FILE_CHAR_DEL) {
3621 1.1 reinoud memset(&fid->icb, 0 , sizeof(struct long_ad));
3622 1.1 reinoud if (context.dscrver == 2) {
3623 1.1 reinoud uint8_t *cpos;
3624 1.1 reinoud /* compression IDs are preserved */
3625 1.1 reinoud cpos = (fid->data + udf_rw16(fid->l_iu));
3626 1.1 reinoud if (*cpos == 254)
3627 1.1 reinoud *cpos = 8;
3628 1.1 reinoud if (*cpos == 255)
3629 1.1 reinoud *cpos = 16;
3630 1.1 reinoud }
3631 1.1 reinoud }
3632 1.1 reinoud
3633 1.1 reinoud fpos += fid_len;
3634 1.1 reinoud bpos += fid_len;
3635 1.1 reinoud rest_len -= fid_len;
3636 1.1 reinoud assert(rest_len >= 0);
3637 1.1 reinoud }
3638 1.1 reinoud if (parent_missing) {
3639 1.1 reinoud /* this should be valid or we're in LALA land */
3640 1.1 reinoud assert(last_empty_fid);
3641 1.1 reinoud pwarn("%s : implementation limit, can't fix up missing parent node yet!\n",
3642 1.1 reinoud udf_node_path(node));
3643 1.1 reinoud }
3644 1.1 reinoud
3645 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3646 1.1 reinoud
3647 1.1 reinoud fid_context.fid_offset = 0;
3648 1.1 reinoud fid_context.data_left = node->found.inf_len;
3649 1.1 reinoud error = udf_process_file(dscr, context.fids_part,
3650 1.1 reinoud &node->directory,
3651 1.1 reinoud AD_ADJUST_FIDS | AD_SAVE_FILE,
3652 1.1 reinoud &fid_context);
3653 1.1 reinoud if (error)
3654 1.1 reinoud pwarn("Failed to write out directory!\n");
3655 1.7 reinoud (void) fpos;
3656 1.1 reinoud }
3657 1.1 reinoud
3658 1.1 reinoud
3659 1.1 reinoud static void
3660 1.1 reinoud udf_node_pass3_writeout_update(struct udf_fsck_node *node, union dscrptr *dscr)
3661 1.1 reinoud {
3662 1.1 reinoud struct file_entry *fe = NULL;
3663 1.1 reinoud struct extfile_entry *efe = NULL;
3664 1.1 reinoud int error;
3665 1.1 reinoud
3666 1.1 reinoud vat_writeout = 1;
3667 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
3668 1.1 reinoud fe = (struct file_entry *) dscr;
3669 1.1 reinoud fe->inf_len = udf_rw64(node->declared.inf_len);
3670 1.1 reinoud fe->logblks_rec = udf_rw64(node->declared.logblks_rec);
3671 1.1 reinoud fe->link_cnt = udf_rw16(node->link_count);
3672 1.1 reinoud fe->unique_id = udf_rw64(node->unique_id);
3673 1.1 reinoud }
3674 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
3675 1.1 reinoud efe = (struct extfile_entry *) dscr;
3676 1.1 reinoud efe->inf_len = udf_rw64(node->declared.inf_len);
3677 1.1 reinoud efe->obj_size = udf_rw64(node->declared.obj_size);
3678 1.1 reinoud efe->logblks_rec = udf_rw64(node->declared.logblks_rec);
3679 1.1 reinoud efe->link_cnt = udf_rw16(node->link_count);
3680 1.1 reinoud efe->unique_id = udf_rw64(node->unique_id);
3681 1.1 reinoud /* streamdir directly cleared in dscr */
3682 1.1 reinoud }
3683 1.1 reinoud
3684 1.1 reinoud /* fixup CRC length (if needed) */
3685 1.1 reinoud dscr->tag.desc_crc_len = udf_tagsize(dscr, 1) - sizeof(struct desc_tag);
3686 1.1 reinoud
3687 1.1 reinoud pwarn("%s : updating node\n", udf_node_path(node));
3688 1.1 reinoud error = udf_write_dscr_virt(dscr, udf_rw32(node->loc.loc.lb_num),
3689 1.1 reinoud udf_rw16(node->loc.loc.part_num), 1);
3690 1.1 reinoud udf_shadow_VAT_in_use(&node->loc);
3691 1.1 reinoud if (error)
3692 1.1 reinoud pwarn("%s failed\n", __func__);
3693 1.1 reinoud }
3694 1.1 reinoud
3695 1.1 reinoud
3696 1.1 reinoud static void
3697 1.1 reinoud udf_create_new_space_bitmaps_and_reset_freespace(void)
3698 1.1 reinoud {
3699 1.1 reinoud struct space_bitmap_desc *sbd, *new_sbd;
3700 1.1 reinoud struct part_desc *part;
3701 1.1 reinoud struct part_hdr_desc *phd;
3702 1.1 reinoud uint32_t bitmap_len, bitmap_lb, bitmap_numlb;
3703 1.1 reinoud uint32_t cnt;
3704 1.1 reinoud int i, p, dscr_size;
3705 1.1 reinoud int error;
3706 1.1 reinoud
3707 1.1 reinoud /* copy recorded freespace info and clear counters */
3708 1.1 reinoud for (i = 0; i < UDF_PARTITIONS; i++) {
3709 1.1 reinoud recorded_part_free[i] = context.part_free[i];
3710 1.1 reinoud context.part_free[i] = context.part_size[i];
3711 1.1 reinoud }
3712 1.1 reinoud
3713 1.1 reinoud /* clone existing bitmaps */
3714 1.1 reinoud for (i = 0; i < UDF_PARTITIONS; i++) {
3715 1.1 reinoud sbd = context.part_unalloc_bits[i];
3716 1.1 reinoud recorded_part_unalloc_bits[i] = sbd;
3717 1.1 reinoud if (sbd == NULL)
3718 1.1 reinoud continue;
3719 1.1 reinoud dscr_size = udf_tagsize((union dscrptr *) sbd,
3720 1.1 reinoud context.sector_size);
3721 1.1 reinoud new_sbd = calloc(1, dscr_size);
3722 1.1 reinoud memcpy(new_sbd, sbd, sizeof(struct space_bitmap_desc)-1);
3723 1.1 reinoud
3724 1.1 reinoud /* fill space with 0xff to indicate free */
3725 1.1 reinoud for (cnt = 0; cnt < udf_rw32(sbd->num_bytes); cnt++)
3726 1.1 reinoud new_sbd->data[cnt] = 0xff;
3727 1.1 reinoud
3728 1.1 reinoud context.part_unalloc_bits[i] = new_sbd;
3729 1.1 reinoud }
3730 1.1 reinoud
3731 1.1 reinoud /* allocate the space bitmaps themselves (normally one) */
3732 1.1 reinoud for (i = 0; i < UDF_PARTITIONS; i++) {
3733 1.1 reinoud part = context.partitions[i];
3734 1.1 reinoud if (!part)
3735 1.1 reinoud continue;
3736 1.1 reinoud
3737 1.1 reinoud phd = &part->pd_part_hdr;
3738 1.1 reinoud bitmap_len = udf_rw32(phd->unalloc_space_bitmap.len);
3739 1.1 reinoud bitmap_lb = udf_rw32(phd->unalloc_space_bitmap.lb_num);
3740 1.1 reinoud if (bitmap_len == 0)
3741 1.1 reinoud continue;
3742 1.1 reinoud
3743 1.1 reinoud bitmap_numlb = udf_bytes_to_sectors(bitmap_len);
3744 1.1 reinoud sbd = context.part_unalloc_bits[i];
3745 1.1 reinoud assert(sbd);
3746 1.1 reinoud
3747 1.1 reinoud udf_mark_allocated(bitmap_lb, context.vtop[i], bitmap_numlb);
3748 1.1 reinoud }
3749 1.1 reinoud
3750 1.1 reinoud /* special case for metadata partition */
3751 1.1 reinoud if (context.format_flags & FORMAT_META) {
3752 1.1 reinoud i = context.metadata_part;
3753 1.1 reinoud p = context.vtop[i];
3754 1.1 reinoud assert(context.vtop_tp[i] == UDF_VTOP_TYPE_META);
3755 1.1 reinoud error = udf_process_file((union dscrptr *) context.meta_file,
3756 1.1 reinoud p, NULL, AD_MARK_AS_USED, NULL);
3757 1.1 reinoud error = udf_process_file((union dscrptr *) context.meta_mirror,
3758 1.1 reinoud p, NULL, AD_MARK_AS_USED, NULL);
3759 1.1 reinoud if (context.meta_bitmap) {
3760 1.1 reinoud error = udf_process_file(
3761 1.1 reinoud (union dscrptr *) context.meta_bitmap,
3762 1.1 reinoud p, NULL, AD_MARK_AS_USED, NULL);
3763 1.1 reinoud assert(error == 0);
3764 1.1 reinoud }
3765 1.1 reinoud }
3766 1.1 reinoud
3767 1.1 reinoud /* mark fsd allocation ! */
3768 1.1 reinoud udf_mark_allocated(udf_rw32(context.fileset_desc->tag.tag_loc),
3769 1.1 reinoud context.metadata_part, 1);
3770 1.1 reinoud }
3771 1.1 reinoud
3772 1.1 reinoud
3773 1.1 reinoud static void
3774 1.1 reinoud udf_shadow_VAT_in_use(struct long_ad *loc)
3775 1.1 reinoud {
3776 1.1 reinoud uint32_t i;
3777 1.1 reinoud uint8_t *vat_pos, *shadow_vat_pos;
3778 1.1 reinoud
3779 1.1 reinoud if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
3780 1.1 reinoud return;
3781 1.1 reinoud
3782 1.1 reinoud i = udf_rw32(loc->loc.lb_num);
3783 1.1 reinoud vat_pos = context.vat_contents + context.vat_start + i*4;
3784 1.1 reinoud shadow_vat_pos = shadow_vat_contents + context.vat_start + i*4;
3785 1.1 reinoud /* keeping endian */
3786 1.1 reinoud *(uint32_t *) shadow_vat_pos = *(uint32_t *) vat_pos;
3787 1.1 reinoud }
3788 1.1 reinoud
3789 1.1 reinoud
3790 1.1 reinoud static void
3791 1.1 reinoud udf_create_shadow_VAT(void)
3792 1.1 reinoud {
3793 1.1 reinoud struct long_ad fsd_loc;
3794 1.1 reinoud uint32_t vat_entries, i;
3795 1.1 reinoud uint8_t *vat_pos;
3796 1.1 reinoud
3797 1.1 reinoud if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
3798 1.1 reinoud return;
3799 1.1 reinoud
3800 1.1 reinoud shadow_vat_contents = calloc(1, context.vat_allocated);
3801 1.1 reinoud assert(shadow_vat_contents);
3802 1.1 reinoud memcpy(shadow_vat_contents, context.vat_contents, context.vat_size);
3803 1.1 reinoud
3804 1.1 reinoud vat_entries = (context.vat_size - context.vat_start)/4;
3805 1.1 reinoud for (i = 0; i < vat_entries; i++) {
3806 1.1 reinoud vat_pos = shadow_vat_contents + context.vat_start + i*4;
3807 1.1 reinoud *(uint32_t *) vat_pos = udf_rw32(0xffffffff);
3808 1.1 reinoud }
3809 1.1 reinoud
3810 1.1 reinoud /*
3811 1.1 reinoud * Record our FSD in this shadow VAT since its the only one outside
3812 1.1 reinoud * the nodes.
3813 1.1 reinoud */
3814 1.1 reinoud memset(&fsd_loc, 0, sizeof(struct long_ad));
3815 1.1 reinoud fsd_loc.loc.lb_num = context.fileset_desc->tag.tag_loc;
3816 1.1 reinoud udf_shadow_VAT_in_use(&fsd_loc);
3817 1.1 reinoud }
3818 1.1 reinoud
3819 1.1 reinoud
3820 1.1 reinoud static void
3821 1.1 reinoud udf_check_shadow_VAT(void)
3822 1.1 reinoud {
3823 1.1 reinoud uint32_t vat_entries, i;
3824 1.1 reinoud uint8_t *vat_pos, *shadow_vat_pos;
3825 1.1 reinoud int difference = 0;
3826 1.1 reinoud
3827 1.1 reinoud if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
3828 1.1 reinoud return;
3829 1.1 reinoud
3830 1.1 reinoud vat_entries = (context.vat_size - context.vat_start)/4;
3831 1.1 reinoud for (i = 0; i < vat_entries; i++) {
3832 1.1 reinoud vat_pos = context.vat_contents + context.vat_start + i*4;
3833 1.1 reinoud shadow_vat_pos = shadow_vat_contents + context.vat_start + i*4;
3834 1.1 reinoud if (*(uint32_t *) vat_pos != *(uint32_t *) shadow_vat_pos) {
3835 1.1 reinoud difference++;
3836 1.1 reinoud }
3837 1.1 reinoud }
3838 1.1 reinoud memcpy(context.vat_contents, shadow_vat_contents, context.vat_size);
3839 1.1 reinoud if (difference) {
3840 1.1 reinoud if (!preen)
3841 1.1 reinoud printf("\t\t");
3842 1.1 reinoud pwarn("%d unused VAT entries cleaned\n", difference);
3843 1.1 reinoud vat_writeout = 1;
3844 1.1 reinoud }
3845 1.1 reinoud }
3846 1.1 reinoud
3847 1.1 reinoud
3848 1.1 reinoud static int
3849 1.1 reinoud udf_check_directory_tree(void)
3850 1.1 reinoud {
3851 1.1 reinoud union dscrptr *dscr;
3852 1.1 reinoud struct udf_fsck_node *root_node, *sys_stream_node;
3853 1.1 reinoud struct udf_fsck_node *cur_node, *next_node;
3854 1.1 reinoud struct long_ad root_icb, sys_stream_icb;
3855 1.1 reinoud bool dont_repair;
3856 1.1 reinoud int entry, error;
3857 1.1 reinoud
3858 1.1 reinoud assert(TAILQ_EMPTY(&fs_nodes));
3859 1.1 reinoud
3860 1.1 reinoud /* (re)init queues and hash lists */
3861 1.1 reinoud TAILQ_INIT(&fs_nodes);
3862 1.1 reinoud TAILQ_INIT(&fsck_overlaps);
3863 1.1 reinoud for (int i = 0; i < HASH_HASHSIZE; i++)
3864 1.1 reinoud LIST_INIT(&fs_nodes_hash[i]);
3865 1.1 reinoud
3866 1.1 reinoud /* create a new empty copy of the space bitmaps */
3867 1.1 reinoud udf_create_new_space_bitmaps_and_reset_freespace();
3868 1.1 reinoud udf_create_shadow_VAT();
3869 1.1 reinoud
3870 1.1 reinoud /* start from the root */
3871 1.1 reinoud root_icb = context.fileset_desc->rootdir_icb;
3872 1.1 reinoud sys_stream_icb = context.fileset_desc->streamdir_icb;
3873 1.1 reinoud
3874 1.1 reinoud root_node = udf_new_fsck_node(NULL, &root_icb, strdup(""));
3875 1.1 reinoud assert(root_node);
3876 1.1 reinoud TAILQ_INSERT_TAIL(&fs_nodes, root_node, next);
3877 1.1 reinoud entry = udf_calc_node_hash(&root_node->loc);
3878 1.1 reinoud LIST_INSERT_HEAD(&fs_nodes_hash[entry], root_node, next_hash);
3879 1.1 reinoud
3880 1.1 reinoud sys_stream_node = NULL;
3881 1.1 reinoud if (sys_stream_icb.len) {
3882 1.1 reinoud sys_stream_node = udf_new_fsck_node(NULL, &sys_stream_icb, strdup("#"));
3883 1.1 reinoud assert(sys_stream_node);
3884 1.1 reinoud sys_stream_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_DIR;
3885 1.1 reinoud
3886 1.1 reinoud TAILQ_INSERT_TAIL(&fs_nodes, sys_stream_node, next);
3887 1.1 reinoud entry = udf_calc_node_hash(&sys_stream_node->loc);
3888 1.1 reinoud LIST_INSERT_HEAD(&fs_nodes_hash[entry], sys_stream_node, next_hash);
3889 1.1 reinoud }
3890 1.1 reinoud
3891 1.1 reinoud /* pass 1 */
3892 1.1 reinoud if (!preen)
3893 1.1 reinoud printf("\tPass 1, reading in directory trees\n");
3894 1.1 reinoud
3895 1.1 reinoud context.unique_id = MAX(0x10, context.unique_id);
3896 1.1 reinoud TAILQ_FOREACH(cur_node, &fs_nodes, next) {
3897 1.1 reinoud /* read in node */
3898 1.1 reinoud error = udf_read_node_dscr(cur_node, &dscr);
3899 1.1 reinoud if (!error)
3900 1.1 reinoud error = udf_extract_node_info(cur_node, dscr, 0);
3901 1.1 reinoud if (error) {
3902 1.1 reinoud pwarn("%s : invalid reference or bad descriptor, DELETING\n",
3903 1.1 reinoud udf_node_path(cur_node));
3904 1.1 reinoud udf_recursive_keep(cur_node);
3905 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_NOTFOUND;
3906 1.1 reinoud if (cur_node->parent) {
3907 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR)
3908 1.1 reinoud cur_node->parent->fsck_flags |=
3909 1.1 reinoud FSCK_NODE_FLAG_WIPE_STREAM_DIR;
3910 1.1 reinoud else
3911 1.1 reinoud cur_node->parent->fsck_flags |=
3912 1.1 reinoud FSCK_NODE_FLAG_REPAIRDIR;
3913 1.1 reinoud ;
3914 1.1 reinoud }
3915 1.1 reinoud free(dscr);
3916 1.1 reinoud continue;
3917 1.1 reinoud }
3918 1.1 reinoud
3919 1.1 reinoud if (print_info) {
3920 1.1 reinoud pwarn("Processing %s\n", udf_node_path(cur_node));
3921 1.1 reinoud print_info = 0;
3922 1.1 reinoud }
3923 1.1 reinoud
3924 1.1 reinoud /* directory found in stream directory? */
3925 1.1 reinoud if (cur_node->parent &&
3926 1.1 reinoud (cur_node->parent->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR) &&
3927 1.1 reinoud (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY))
3928 1.1 reinoud {
3929 1.1 reinoud pwarn("%s : specification violation, directory in stream directory\n",
3930 1.1 reinoud udf_node_path(cur_node));
3931 1.1 reinoud if (ask(0, "Clear directory")) {
3932 1.1 reinoud udf_recursive_keep(cur_node);
3933 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_NOTFOUND;
3934 1.1 reinoud cur_node->parent->fsck_flags |=
3935 1.1 reinoud FSCK_NODE_FLAG_REPAIRDIR;
3936 1.1 reinoud continue;
3937 1.1 reinoud }
3938 1.1 reinoud }
3939 1.1 reinoud error = udf_process_node_pass1(cur_node, dscr);
3940 1.1 reinoud free(dscr);
3941 1.1 reinoud
3942 1.1 reinoud if (error)
3943 1.1 reinoud return error;
3944 1.1 reinoud }
3945 1.1 reinoud
3946 1.1 reinoud /* pass 1b, if there is overlap, find matching pairs */
3947 1.1 reinoud dont_repair = false;
3948 1.1 reinoud if (!TAILQ_EMPTY(&fsck_overlaps)) {
3949 1.1 reinoud struct udf_fsck_overlap *overlap;
3950 1.1 reinoud
3951 1.1 reinoud dont_repair = true;
3952 1.1 reinoud pwarn("*** Overlaps detected! rescanning tree for matching pairs ***\n");
3953 1.1 reinoud TAILQ_FOREACH(cur_node, &fs_nodes, next) {
3954 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)
3955 1.1 reinoud continue;
3956 1.1 reinoud
3957 1.1 reinoud error = udf_read_node_dscr(cur_node, &dscr);
3958 1.1 reinoud /* should not fail differently */
3959 1.1 reinoud
3960 1.1 reinoud if (print_info) {
3961 1.1 reinoud pwarn("Processing %s\n", udf_node_path(cur_node));
3962 1.1 reinoud print_info = 0;
3963 1.1 reinoud }
3964 1.1 reinoud
3965 1.1 reinoud error = udf_process_file(
3966 1.1 reinoud dscr,
3967 1.1 reinoud udf_rw16(cur_node->loc.loc.part_num),
3968 1.1 reinoud NULL,
3969 1.1 reinoud AD_FIND_OVERLAP_PAIR,
3970 1.1 reinoud (void *) cur_node);
3971 1.1 reinoud /* shouldn't fail */
3972 1.1 reinoud
3973 1.1 reinoud free(dscr);
3974 1.1 reinoud }
3975 1.1 reinoud TAILQ_FOREACH(overlap, &fsck_overlaps, next) {
3976 1.1 reinoud pwarn("%s :overlaps with %s\n",
3977 1.1 reinoud udf_node_path(overlap->node),
3978 1.1 reinoud udf_node_path(overlap->node2));
3979 1.1 reinoud }
3980 1.1 reinoud if (!preen)
3981 1.1 reinoud printf("\n");
3982 1.1 reinoud pwarn("*** The following files/directories need to be copied/evacuated:\n");
3983 1.1 reinoud TAILQ_FOREACH(cur_node, &fs_nodes, next) {
3984 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_OVERLAP) {
3985 1.1 reinoud pwarn("%s : found OVERLAP, evacuate\n",
3986 1.1 reinoud udf_node_path(cur_node));
3987 1.1 reinoud }
3988 1.1 reinoud }
3989 1.1 reinoud }
3990 1.1 reinoud if (dont_repair) {
3991 1.1 reinoud if (!preen)
3992 1.1 reinoud printf("\n");
3993 1.1 reinoud pwarn("*** Skipping further repair, only updating free space map if needed\n");
3994 1.1 reinoud pwarn("*** After deep copying and/or evacuation of these files/directories,\n");
3995 1.1 reinoud pwarn("*** remove files/directories and re-run fsck_udf\n");
3996 1.1 reinoud error = udf_prepare_writing();
3997 1.1 reinoud if (error)
3998 1.1 reinoud return error;
3999 1.1 reinoud
4000 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_OPEN);
4001 1.1 reinoud return 0;
4002 1.1 reinoud }
4003 1.1 reinoud
4004 1.1 reinoud /* pass 2a, checking link counts, object sizes and count files/dirs */
4005 1.1 reinoud if (!preen)
4006 1.1 reinoud printf("\n\tPass 2, checking link counts, object sizes, stats and cleaning up\n");
4007 1.1 reinoud
4008 1.1 reinoud TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4009 1.1 reinoud /* not sane to process files/directories that are not found */
4010 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)
4011 1.1 reinoud continue;
4012 1.1 reinoud
4013 1.1 reinoud /* shadow VAT */
4014 1.1 reinoud udf_shadow_VAT_in_use(&cur_node->loc);
4015 1.1 reinoud
4016 1.1 reinoud /* link counts */
4017 1.1 reinoud if (cur_node->found_link_count != cur_node->link_count) {
4018 1.1 reinoud pwarn("%s : link count incorrect; "
4019 1.1 reinoud "%u instead of declared %u : FIXED\n",
4020 1.1 reinoud udf_node_path(cur_node),
4021 1.1 reinoud cur_node->found_link_count, cur_node->link_count);
4022 1.1 reinoud cur_node->link_count = cur_node->found_link_count;
4023 1.1 reinoud udf_recursive_keep(cur_node);
4024 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4025 1.1 reinoud }
4026 1.1 reinoud
4027 1.1 reinoud /* object sizes */
4028 1.1 reinoud if (cur_node->declared.obj_size != cur_node->found.obj_size) {
4029 1.1 reinoud pwarn("%s : recorded object size incorrect; "
4030 1.3 martin "%" PRIu64 " instead of declared %" PRIu64 "\n",
4031 1.1 reinoud udf_node_path(cur_node),
4032 1.1 reinoud cur_node->found.obj_size, cur_node->declared.obj_size);
4033 1.1 reinoud cur_node->declared.obj_size = cur_node->found.obj_size;
4034 1.1 reinoud udf_recursive_keep(cur_node);
4035 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4036 1.1 reinoud }
4037 1.1 reinoud
4038 1.1 reinoud /* XXX TODO XXX times */
4039 1.1 reinoud /* XXX TODO XXX extended attributes location for UDF < 1.50 */
4040 1.1 reinoud
4041 1.1 reinoud /* validity of UniqueID check */
4042 1.1 reinoud if (cur_node->parent) {
4043 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_NEW_UNIQUE_ID) {
4044 1.1 reinoud pwarn("%s : assigning new UniqueID\n",
4045 1.1 reinoud udf_node_path(cur_node));
4046 1.1 reinoud cur_node->unique_id = udf_rw64(context.unique_id);
4047 1.1 reinoud udf_advance_uniqueid();
4048 1.1 reinoud udf_recursive_keep(cur_node);
4049 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4050 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY)
4051 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
4052 1.1 reinoud cur_node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
4053 1.1 reinoud }
4054 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_COPY_PARENT_ID) {
4055 1.1 reinoud /* work already done but make note to operator */
4056 1.1 reinoud pwarn("%s : fixing stream UniqueID to match parent\n",
4057 1.1 reinoud udf_node_path(cur_node));
4058 1.1 reinoud }
4059 1.1 reinoud } else {
4060 1.1 reinoud if (cur_node->unique_id != 0) {
4061 1.1 reinoud pwarn("%s : bad UniqueID, zeroing\n",
4062 1.1 reinoud udf_node_path(cur_node));
4063 1.1 reinoud cur_node->unique_id = 0;
4064 1.1 reinoud cur_node->fsck_flags |=
4065 1.1 reinoud FSCK_NODE_FLAG_DIRTY | FSCK_NODE_FLAG_REPAIRDIR;
4066 1.1 reinoud }
4067 1.1 reinoud }
4068 1.1 reinoud
4069 1.1 reinoud /* keep nodes in a repairing dir */
4070 1.1 reinoud if (cur_node->parent)
4071 1.1 reinoud if (cur_node->parent->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR)
4072 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_KEEP;
4073 1.1 reinoud
4074 1.1 reinoud /* stream directories and files in it are not included */
4075 1.1 reinoud if (!(cur_node->fsck_flags & FSCK_NODE_FLAG_STREAM)) {
4076 1.1 reinoud /* files / directories counting */
4077 1.1 reinoud int link_count = cur_node->found_link_count;
4078 1.1 reinoud
4079 1.1 reinoud /* stream directories don't count as link ECMA 4/14.9.6 */
4080 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_HAS_STREAM_DIR)
4081 1.1 reinoud link_count--;
4082 1.1 reinoud
4083 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY)
4084 1.1 reinoud context.num_directories++;
4085 1.6 riastrad else
4086 1.1 reinoud context.num_files += link_count;
4087 1.1 reinoud ;
4088 1.1 reinoud }
4089 1.1 reinoud }
4090 1.1 reinoud
4091 1.1 reinoud /* pass 2b, cleaning */
4092 1.1 reinoud open_integrity = 0;
4093 1.1 reinoud TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4094 1.1 reinoud /* can we remove the node? (to save memory) */
4095 1.1 reinoud if (FSCK_NODE_FLAG_OK(cur_node->fsck_flags)) {
4096 1.1 reinoud TAILQ_REMOVE(&fs_nodes, cur_node, next);
4097 1.1 reinoud LIST_REMOVE(cur_node, next_hash);
4098 1.1 reinoud free(cur_node->directory);
4099 1.1 reinoud bzero(cur_node, sizeof(struct udf_fsck_node));
4100 1.1 reinoud free(cur_node);
4101 1.1 reinoud } else {
4102 1.1 reinoud /* else keep erroring node */
4103 1.1 reinoud open_integrity = 1;
4104 1.1 reinoud }
4105 1.1 reinoud }
4106 1.1 reinoud
4107 1.1 reinoud if (!preen)
4108 1.1 reinoud printf("\n\tPreparing disc for writing\n");
4109 1.1 reinoud error = udf_prepare_writing();
4110 1.1 reinoud if (error)
4111 1.1 reinoud return error;
4112 1.1 reinoud
4113 1.1 reinoud if (open_integrity)
4114 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_OPEN);
4115 1.1 reinoud
4116 1.1 reinoud /* pass 3 */
4117 1.1 reinoud if (!preen)
4118 1.1 reinoud printf("\n\tPass 3, fix errors\n");
4119 1.1 reinoud
4120 1.1 reinoud TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4121 1.1 reinoud /* not sane to process files/directories that are not found */
4122 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)
4123 1.1 reinoud continue;
4124 1.1 reinoud
4125 1.1 reinoud /* only interested in bad nodes */
4126 1.1 reinoud if (FSCK_NODE_FLAG_OK(cur_node->fsck_flags))
4127 1.1 reinoud continue;
4128 1.1 reinoud
4129 1.1 reinoud error = udf_read_node_dscr(cur_node, &dscr);
4130 1.1 reinoud /* should not fail differently */
4131 1.1 reinoud
4132 1.1 reinoud /* repair directories */
4133 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR)
4134 1.1 reinoud udf_node_pass3_repairdir(cur_node, dscr);
4135 1.1 reinoud
4136 1.1 reinoud /* remove invalid stream directories */
4137 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_WIPE_STREAM_DIR) {
4138 1.1 reinoud assert(udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY);
4139 1.1 reinoud bzero(&dscr->efe.streamdir_icb, sizeof(struct long_ad));
4140 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4141 1.1 reinoud }
4142 1.1 reinoud
4143 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRTY)
4144 1.1 reinoud udf_node_pass3_writeout_update(cur_node, dscr);
4145 1.1 reinoud free(dscr);
4146 1.1 reinoud }
4147 1.1 reinoud udf_check_shadow_VAT();
4148 1.1 reinoud
4149 1.1 reinoud return 0;
4150 1.1 reinoud }
4151 1.1 reinoud
4152 1.1 reinoud
4153 1.1 reinoud static void
4154 1.1 reinoud udf_cleanup_after_check(void)
4155 1.1 reinoud {
4156 1.1 reinoud struct udf_fsck_node *cur_node, *next_node;
4157 1.1 reinoud
4158 1.1 reinoud /* XXX yes, there are some small memory leaks here */
4159 1.1 reinoud
4160 1.1 reinoud /* clean old node info from previous checks */
4161 1.1 reinoud TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4162 1.1 reinoud TAILQ_REMOVE(&fs_nodes, cur_node, next);
4163 1.1 reinoud LIST_REMOVE(cur_node, next_hash);
4164 1.1 reinoud free(cur_node->directory);
4165 1.1 reinoud free(cur_node);
4166 1.1 reinoud }
4167 1.1 reinoud
4168 1.1 reinoud /* free partition related info */
4169 1.1 reinoud for (int i = 0; i < UDF_PARTITIONS; i++) {
4170 1.1 reinoud free(context.partitions[i]);
4171 1.1 reinoud free(context.part_unalloc_bits[i]);
4172 1.1 reinoud free(context.part_freed_bits[i]);
4173 1.1 reinoud }
4174 1.1 reinoud
4175 1.1 reinoud /* only free potentional big blobs */
4176 1.1 reinoud free(context.vat_contents);
4177 1.1 reinoud free(context.lvint_history);
4178 1.1 reinoud
4179 1.1 reinoud free(shadow_vat_contents);
4180 1.1 reinoud shadow_vat_contents = NULL;
4181 1.1 reinoud }
4182 1.1 reinoud
4183 1.1 reinoud
4184 1.1 reinoud static int
4185 1.1 reinoud checkfilesys(char *given_dev)
4186 1.1 reinoud {
4187 1.1 reinoud struct mmc_trackinfo ti;
4188 1.1 reinoud int open_flags;
4189 1.1 reinoud int error;
4190 1.1 reinoud
4191 1.1 reinoud udf_init_create_context();
4192 1.1 reinoud context.app_name = "*NetBSD UDF";
4193 1.1 reinoud context.app_version_main = APP_VERSION_MAIN;
4194 1.1 reinoud context.app_version_sub = APP_VERSION_SUB;
4195 1.1 reinoud context.impl_name = IMPL_NAME;
4196 1.1 reinoud
4197 1.1 reinoud emul_mmc_profile = -1; /* invalid->no emulation */
4198 1.1 reinoud emul_packetsize = 1; /* reasonable default */
4199 1.1 reinoud emul_sectorsize = 512; /* minimum allowed sector size */
4200 1.1 reinoud emul_size = 0; /* empty */
4201 1.1 reinoud
4202 1.1 reinoud if (!preen)
4203 1.1 reinoud pwarn("** Checking UDF file system on %s\n", given_dev);
4204 1.1 reinoud
4205 1.1 reinoud /* reset sticky flags */
4206 1.1 reinoud rdonly = rdonly_flag;
4207 1.1 reinoud undo_opening_session = 0; /* trying to undo opening of last crippled session */
4208 1.1 reinoud vat_writeout = 0; /* to write out the VAT anyway */
4209 1.1 reinoud
4210 1.1 reinoud /* open disc device or emulated file */
4211 1.1 reinoud open_flags = rdonly ? O_RDONLY : O_RDWR;
4212 1.1 reinoud if (udf_opendisc(given_dev, open_flags)) {
4213 1.1 reinoud udf_closedisc();
4214 1.1 reinoud warnx("can't open %s", given_dev);
4215 1.1 reinoud return FSCK_EXIT_CHECK_FAILED;
4216 1.1 reinoud }
4217 1.1 reinoud
4218 1.1 reinoud if (!preen)
4219 1.1 reinoud pwarn("** Phase 1 - discovering format from disc\n\n");
4220 1.1 reinoud
4221 1.1 reinoud /* check if it is an empty disc or no disc in present */
4222 1.1 reinoud ti.tracknr = mmc_discinfo.first_track;
4223 1.1 reinoud error = udf_update_trackinfo(&ti);
4224 1.1 reinoud if (error || (ti.flags & MMC_TRACKINFO_BLANK)) {
4225 1.1 reinoud /* no use erroring out */
4226 1.1 reinoud pwarn("Empty disc\n");
4227 1.1 reinoud return FSCK_EXIT_OK;
4228 1.1 reinoud }
4229 1.1 reinoud
4230 1.1 reinoud context.format_flags = 0;
4231 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL)
4232 1.1 reinoud context.format_flags |= FORMAT_SEQUENTIAL;
4233 1.1 reinoud
4234 1.1 reinoud if ((context.format_flags & FORMAT_SEQUENTIAL) &&
4235 1.1 reinoud ((mmc_discinfo.disc_state == MMC_STATE_CLOSED) ||
4236 1.1 reinoud (mmc_discinfo.disc_state == MMC_STATE_FULL))) {
4237 1.1 reinoud pwarn("Disc is closed or full, can't modify disc\n");
4238 1.1 reinoud rdonly = 1;
4239 1.1 reinoud }
4240 1.1 reinoud
4241 1.1 reinoud if (target_session) {
4242 1.1 reinoud context.create_new_session = 1;
4243 1.1 reinoud if (target_session < 0)
4244 1.1 reinoud target_session += mmc_discinfo.num_sessions;
4245 1.1 reinoud } else {
4246 1.1 reinoud target_session = mmc_discinfo.num_sessions;
4247 1.1 reinoud if (mmc_discinfo.last_session_state == MMC_STATE_EMPTY)
4248 1.1 reinoud target_session--;
4249 1.1 reinoud }
4250 1.1 reinoud
4251 1.1 reinoud error = udf_get_anchors();
4252 1.1 reinoud if (error) {
4253 1.1 reinoud udf_closedisc();
4254 1.1 reinoud pwarn("Failed to retrieve anchors; can't check file system\n");
4255 1.1 reinoud return FSCK_EXIT_CHECK_FAILED;
4256 1.1 reinoud }
4257 1.1 reinoud
4258 1.1 reinoud udf_check_vrs9660();
4259 1.1 reinoud
4260 1.1 reinoud /* get both VRS areas */
4261 1.1 reinoud error = udf_check_VDS_areas();
4262 1.1 reinoud if (error) {
4263 1.1 reinoud udf_closedisc();
4264 1.1 reinoud pwarn("Failure reading volume descriptors, disc might be toast\n");
4265 1.1 reinoud return FSCK_EXIT_CHECK_FAILED;
4266 1.1 reinoud }
4267 1.1 reinoud
4268 1.1 reinoud if (udf_rw32(context.logvol_integrity->integrity_type) ==
4269 1.1 reinoud UDF_INTEGRITY_CLOSED) {
4270 1.1 reinoud if (!force) {
4271 1.1 reinoud pwarn("** File system is clean; not checking\n");
4272 1.1 reinoud return FSCK_EXIT_OK;
4273 1.1 reinoud }
4274 1.1 reinoud pwarn("** File system is already clean\n");
4275 1.1 reinoud if (!preen)
4276 1.1 reinoud pwarn("\n");
4277 1.1 reinoud } else {
4278 1.1 reinoud pwarn("** File system not closed properly\n");
4279 1.1 reinoud if (!preen)
4280 1.1 reinoud printf("\n");
4281 1.1 reinoud }
4282 1.1 reinoud
4283 1.1 reinoud /*
4284 1.1 reinoud * Only now read in free/unallocated space bitmap. If it reads in fine
4285 1.1 reinoud * it doesn't mean its contents is valid though. Sets partition
4286 1.1 reinoud * lengths too.
4287 1.1 reinoud */
4288 1.1 reinoud error = udf_readin_partitions_free_space();
4289 1.1 reinoud if (error) {
4290 1.1 reinoud pwarn("Error during free space bitmap reading\n");
4291 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_OPEN);
4292 1.1 reinoud }
4293 1.1 reinoud
4294 1.1 reinoud if (!preen)
4295 1.1 reinoud pwarn("** Phase 2 - walking directory tree\n");
4296 1.1 reinoud
4297 1.1 reinoud udf_suspend_writing();
4298 1.1 reinoud error = udf_check_directory_tree();
4299 1.1 reinoud if (error) {
4300 1.1 reinoud if ((!rdonly) && ask(0, "Write out modifications made until now"))
4301 1.1 reinoud udf_allow_writing();
4302 1.1 reinoud else
4303 1.1 reinoud pwarn("** Aborting repair, not modifying disc\n");
4304 1.1 reinoud udf_closedisc();
4305 1.1 reinoud return FSCK_EXIT_CHECK_FAILED;
4306 1.1 reinoud }
4307 1.1 reinoud
4308 1.1 reinoud if (!preen)
4309 1.1 reinoud pwarn("\n** Phase 3 - closing volume if needed\n\n");
4310 1.1 reinoud
4311 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */
4312 1.1 reinoud //udf_update_lvintd(UDF_INTEGRITY_OPEN);
4313 1.1 reinoud
4314 1.1 reinoud if (error && rdonly) {
4315 1.1 reinoud pwarn("** Aborting repair, nothing written, disc marked read-only\n");
4316 1.1 reinoud } else {
4317 1.1 reinoud error = udf_close_volume();
4318 1.1 reinoud }
4319 1.1 reinoud
4320 1.1 reinoud udf_closedisc();
4321 1.1 reinoud
4322 1.1 reinoud if (error)
4323 1.1 reinoud return FSCK_EXIT_CHECK_FAILED;
4324 1.1 reinoud return FSCK_EXIT_OK;
4325 1.1 reinoud }
4326 1.1 reinoud
4327 1.1 reinoud
4328 1.1 reinoud static void
4329 1.1 reinoud usage(void)
4330 1.1 reinoud {
4331 1.2 wiz (void)fprintf(stderr, "Usage: %s [-fHnpSsy] file-system ... \n",
4332 1.1 reinoud getprogname());
4333 1.1 reinoud exit(FSCK_EXIT_USAGE);
4334 1.1 reinoud }
4335 1.1 reinoud
4336 1.1 reinoud
4337 1.1 reinoud static void
4338 1.1 reinoud got_siginfo(int signo)
4339 1.1 reinoud {
4340 1.1 reinoud print_info = 1;
4341 1.1 reinoud }
4342 1.1 reinoud
4343 1.1 reinoud
4344 1.1 reinoud int
4345 1.1 reinoud main(int argc, char **argv)
4346 1.1 reinoud {
4347 1.1 reinoud int ret = FSCK_EXIT_OK, erg;
4348 1.1 reinoud int ch;
4349 1.1 reinoud
4350 1.1 reinoud while ((ch = getopt(argc, argv, "ps:SynfH")) != -1) {
4351 1.1 reinoud switch (ch) {
4352 1.1 reinoud case 'H':
4353 1.1 reinoud heuristics = 1;
4354 1.1 reinoud break;
4355 1.1 reinoud case 'f':
4356 1.1 reinoud force = 1;
4357 1.1 reinoud break;
4358 1.1 reinoud case 'n':
4359 1.1 reinoud rdonly_flag = alwaysno = 1;
4360 1.1 reinoud alwaysyes = preen = 0;
4361 1.1 reinoud break;
4362 1.1 reinoud case 'y':
4363 1.1 reinoud alwaysyes = 1;
4364 1.1 reinoud alwaysno = preen = 0;
4365 1.1 reinoud break;
4366 1.1 reinoud case 'p':
4367 1.1 reinoud /* small automatic repairs */
4368 1.1 reinoud preen = 1;
4369 1.1 reinoud alwaysyes = alwaysno = 0;
4370 1.1 reinoud break;
4371 1.1 reinoud case 's':
4372 1.1 reinoud /* session number or relative session */
4373 1.1 reinoud target_session = atoi(optarg);
4374 1.1 reinoud break;
4375 1.1 reinoud case 'S': /* Search for older VATs */
4376 1.1 reinoud search_older_vat = 1;
4377 1.1 reinoud break;
4378 1.1 reinoud
4379 1.1 reinoud default:
4380 1.1 reinoud usage();
4381 1.1 reinoud break;
4382 1.1 reinoud }
4383 1.1 reinoud }
4384 1.1 reinoud argc -= optind;
4385 1.1 reinoud argv += optind;
4386 1.1 reinoud
4387 1.1 reinoud if (!argc)
4388 1.1 reinoud usage();
4389 1.1 reinoud
4390 1.1 reinoud /* TODO SIGINT and SIGQUIT catchers */
4391 1.1 reinoud #if 0
4392 1.1 reinoud if (signal(SIGINT, SIG_IGN) != SIG_IGN)
4393 1.1 reinoud (void) signal(SIGINT, catch);
4394 1.1 reinoud if (preen)
4395 1.1 reinoud (void) signal(SIGQUIT, catch);
4396 1.1 reinoud #endif
4397 1.1 reinoud
4398 1.1 reinoud signal(SIGINFO, got_siginfo);
4399 1.1 reinoud
4400 1.1 reinoud while (--argc >= 0) {
4401 1.1 reinoud setcdevname(*argv, preen);
4402 1.1 reinoud erg = checkfilesys(*argv++);
4403 1.1 reinoud if (erg > ret)
4404 1.1 reinoud ret = erg;
4405 1.1 reinoud if (!preen)
4406 1.1 reinoud printf("\n");
4407 1.1 reinoud udf_cleanup_after_check();
4408 1.1 reinoud }
4409 1.1 reinoud
4410 1.1 reinoud return ret;
4411 1.1 reinoud }
4412 1.1 reinoud
4413 1.1 reinoud
4414 1.1 reinoud /*VARARGS*/
4415 1.4 riastrad static int __printflike(2, 3)
4416 1.1 reinoud ask(int def, const char *fmt, ...)
4417 1.1 reinoud {
4418 1.1 reinoud va_list ap;
4419 1.1 reinoud
4420 1.1 reinoud char prompt[256];
4421 1.1 reinoud int c;
4422 1.1 reinoud
4423 1.1 reinoud va_start(ap, fmt);
4424 1.1 reinoud vsnprintf(prompt, sizeof(prompt), fmt, ap);
4425 1.1 reinoud va_end(ap);
4426 1.1 reinoud if (alwaysyes || rdonly) {
4427 1.1 reinoud pwarn("%s? %s\n", prompt, rdonly ? "no" : "yes");
4428 1.1 reinoud return !rdonly;
4429 1.1 reinoud }
4430 1.1 reinoud if (preen) {
4431 1.1 reinoud pwarn("%s? %s : (default)\n", prompt, def ? "yes" : "no");
4432 1.1 reinoud return def;
4433 1.1 reinoud }
4434 1.1 reinoud
4435 1.1 reinoud do {
4436 1.1 reinoud pwarn("%s? [yn] ", prompt);
4437 1.1 reinoud fflush(stdout);
4438 1.1 reinoud c = getchar();
4439 1.1 reinoud while (c != '\n' && getchar() != '\n')
4440 1.1 reinoud if (feof(stdin))
4441 1.1 reinoud return 0;
4442 1.1 reinoud } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
4443 1.1 reinoud return c == 'y' || c == 'Y';
4444 1.1 reinoud }
4445 1.1 reinoud
4446 1.1 reinoud
4447 1.1 reinoud /*VARARGS*/
4448 1.4 riastrad static int __printflike(2, 3)
4449 1.1 reinoud ask_noauto(int def, const char *fmt, ...)
4450 1.1 reinoud {
4451 1.1 reinoud va_list ap;
4452 1.1 reinoud
4453 1.1 reinoud char prompt[256];
4454 1.1 reinoud int c;
4455 1.1 reinoud
4456 1.1 reinoud va_start(ap, fmt);
4457 1.1 reinoud vsnprintf(prompt, sizeof(prompt), fmt, ap);
4458 1.1 reinoud va_end(ap);
4459 1.1 reinoud #if 0
4460 1.1 reinoud if (preen) {
4461 1.1 reinoud pwarn("%s? %s : (default)\n", prompt, def ? "yes" : "no");
4462 1.1 reinoud return def;
4463 1.1 reinoud }
4464 1.1 reinoud #endif
4465 1.1 reinoud
4466 1.1 reinoud do {
4467 1.1 reinoud pwarn("%s? [yn] ", prompt);
4468 1.1 reinoud fflush(stdout);
4469 1.1 reinoud c = getchar();
4470 1.1 reinoud while (c != '\n' && getchar() != '\n')
4471 1.1 reinoud if (feof(stdin))
4472 1.1 reinoud return 0;
4473 1.1 reinoud } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
4474 1.1 reinoud return c == 'y' || c == 'Y';
4475 1.1 reinoud }
4476