1 1.15 andvar /* $NetBSD: main.c,v 1.15 2025/03/05 22:21:11 andvar 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.15 andvar __RCSID("$NetBSD: main.c,v 1.15 2025/03/05 22:21:11 andvar 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.15 andvar /* XXX why two buffers and not just read descriptor 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.14 mrg vds2_buf = NULL; 2804 1.1 reinoud } 2805 1.1 reinoud if (!error2) { 2806 1.1 reinoud /* retrieve data from VDS 2 */ 2807 1.1 reinoud udf_read_vds_extent(vds2_buf, vds2_size); 2808 1.1 reinoud context.vds_buf = vds2_buf; 2809 1.1 reinoud context.vds_size = vds2_size; 2810 1.1 reinoud free(vds1_buf); 2811 1.14 mrg vds1_buf = NULL; 2812 1.1 reinoud } 2813 1.1 reinoud /* check if all is correct and complete */ 2814 1.1 reinoud error = udf_process_vds(); 2815 1.1 reinoud if (error) 2816 1.1 reinoud return error; 2817 1.1 reinoud 2818 1.1 reinoud /* TODO check if both area's are logically the same */ 2819 1.1 reinoud error = 0; 2820 1.1 reinoud if (!error1 && error2) { 2821 1.1 reinoud /* first OK, second faulty */ 2822 1.1 reinoud pwarn("Backup volume descriptor missing or damaged\n"); 2823 1.1 reinoud if (context.format_flags & FORMAT_SEQUENTIAL) { 2824 1.1 reinoud pwarn("Can't fixup backup volume descriptor on " 2825 1.1 reinoud "SEQUENTIAL media\n"); 2826 1.1 reinoud } else if (ask(1, "Fixup backup volume descriptor")) { 2827 1.1 reinoud error = udf_copy_VDS_area(vds2_buf, vds1_buf); 2828 1.1 reinoud pwarn("\n"); 2829 1.1 reinoud } 2830 1.1 reinoud } 2831 1.1 reinoud if (error1 && !error2) { 2832 1.1 reinoud /* second OK, first faulty */ 2833 1.1 reinoud pwarn("Primary volume descriptor missing or damaged\n"); 2834 1.1 reinoud if (context.format_flags & FORMAT_SEQUENTIAL) { 2835 1.1 reinoud pwarn("Can't fix up primary volume descriptor on " 2836 1.1 reinoud "SEQUENTIAL media\n"); 2837 1.1 reinoud } else if (ask(1, "Fix up primary volume descriptor")) { 2838 1.1 reinoud error = udf_copy_VDS_area(vds1_buf, vds2_buf); 2839 1.1 reinoud } 2840 1.1 reinoud } 2841 1.1 reinoud if (error) 2842 1.1 reinoud pwarn("copying VDS areas failed!\n"); 2843 1.1 reinoud if (!preen) 2844 1.1 reinoud printf("\n"); 2845 1.1 reinoud 2846 1.1 reinoud return error; 2847 1.1 reinoud } 2848 1.1 reinoud 2849 1.1 reinoud /* --------------------------------------------------------------------- */ 2850 1.1 reinoud 2851 1.1 reinoud static int 2852 1.1 reinoud udf_prepare_writing(void) 2853 1.1 reinoud { 2854 1.1 reinoud union dscrptr *zero_dscr, *dscr; 2855 1.1 reinoud struct mmc_trackinfo ti; 2856 1.1 reinoud uint32_t first_lba, loc; 2857 1.1 reinoud int sector_size = context.sector_size; 2858 1.1 reinoud int error; 2859 1.1 reinoud 2860 1.1 reinoud error = udf_prepare_disc(); 2861 1.1 reinoud if (error) { 2862 1.1 reinoud pwarn("*** Preparing disc for writing failed!\n"); 2863 1.1 reinoud return error; 2864 1.1 reinoud } 2865 1.1 reinoud 2866 1.1 reinoud /* if we are not on sequential media, we're done */ 2867 1.13 reinoud if ((context.format_flags & FORMAT_VAT) == 0) 2868 1.1 reinoud return 0; 2869 1.1 reinoud 2870 1.1 reinoud /* if the disc is full, we drop back to read only */ 2871 1.1 reinoud if (mmc_discinfo.disc_state == MMC_STATE_FULL) 2872 1.1 reinoud rdonly = 1; 2873 1.1 reinoud if (rdonly) 2874 1.1 reinoud return 0; 2875 1.1 reinoud 2876 1.1 reinoud /* check if we need to open the last track */ 2877 1.1 reinoud ti.tracknr = mmc_discinfo.last_track_last_session; 2878 1.1 reinoud error = udf_update_trackinfo(&ti); 2879 1.1 reinoud if (error) 2880 1.1 reinoud return error; 2881 1.6 riastrad if (!(ti.flags & MMC_TRACKINFO_BLANK) && 2882 1.1 reinoud (ti.flags & MMC_TRACKINFO_NWA_VALID)) { 2883 1.1 reinoud /* 2884 1.1 reinoud * Not closed; translate next_writable to a position relative to our 2885 1.1 reinoud * backing partition 2886 1.1 reinoud */ 2887 1.1 reinoud context.alloc_pos[context.data_part] = ti.next_writable - 2888 1.1 reinoud udf_rw32(context.partitions[context.data_part]->start_loc); 2889 1.1 reinoud wrtrack_skew = ti.next_writable % layout.blockingnr; 2890 1.1 reinoud return 0; 2891 1.1 reinoud } 2892 1.1 reinoud assert(ti.flags & MMC_TRACKINFO_NWA_VALID); 2893 1.1 reinoud 2894 1.1 reinoud /* just in case */ 2895 1.1 reinoud udf_suspend_writing(); 2896 1.1 reinoud 2897 1.1 reinoud /* 'add' a new track */ 2898 1.1 reinoud udf_update_discinfo(); 2899 1.1 reinoud memset(&context.last_ti, 0, sizeof(struct mmc_trackinfo)); 2900 1.1 reinoud context.last_ti.tracknr = mmc_discinfo.first_track_last_session; 2901 1.1 reinoud (void) udf_update_trackinfo(&context.last_ti); 2902 1.1 reinoud 2903 1.1 reinoud assert(mmc_discinfo.last_session_state == MMC_STATE_EMPTY); 2904 1.1 reinoud first_lba = context.last_ti.track_start; 2905 1.1 reinoud wrtrack_skew = context.last_ti.track_start % layout.blockingnr; 2906 1.1 reinoud 2907 1.1 reinoud /* 2908 1.1 reinoud * location of iso9660 vrs is defined as first sector AFTER 32kb, 2909 1.1 reinoud * minimum `sector size' 2048 2910 1.1 reinoud */ 2911 1.1 reinoud layout.iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size) 2912 1.1 reinoud + first_lba; 2913 1.1 reinoud 2914 1.1 reinoud /* anchor starts at specified offset in sectors */ 2915 1.1 reinoud layout.anchors[0] = first_lba + 256; 2916 1.1 reinoud 2917 1.1 reinoud /* ready for appending, write preamble, we are using overwrite here! */ 2918 1.1 reinoud if ((zero_dscr = calloc(1, context.sector_size)) == NULL) 2919 1.1 reinoud return ENOMEM; 2920 1.1 reinoud loc = first_lba; 2921 1.1 reinoud for (; loc < first_lba + 256; loc++) { 2922 1.1 reinoud if ((error = udf_write_sector(zero_dscr, loc))) { 2923 1.1 reinoud free(zero_dscr); 2924 1.1 reinoud return error; 2925 1.1 reinoud } 2926 1.1 reinoud } 2927 1.1 reinoud free(zero_dscr); 2928 1.1 reinoud 2929 1.1 reinoud /* write new ISO9660 volume recognition sequence */ 2930 1.1 reinoud if ((error = udf_write_iso9660_vrs())) { 2931 1.1 reinoud pwarn("internal error: can't write iso966 VRS in new session!\n"); 2932 1.1 reinoud rdonly = 1; 2933 1.1 reinoud return error; 2934 1.1 reinoud } 2935 1.1 reinoud 2936 1.1 reinoud /* write out our old anchor, VDS spaces will be reused */ 2937 1.1 reinoud assert(context.anchors[0]); 2938 1.1 reinoud dscr = (union dscrptr *) context.anchors[0]; 2939 1.1 reinoud loc = layout.anchors[0]; 2940 1.1 reinoud if ((error = udf_write_dscr_phys(dscr, loc, 1))) { 2941 1.1 reinoud pwarn("internal error: can't write anchor in new session!\n"); 2942 1.1 reinoud rdonly = 1; 2943 1.1 reinoud return error; 2944 1.1 reinoud } 2945 1.1 reinoud 2946 1.1 reinoud context.alloc_pos[context.data_part] = first_lba + 257 - 2947 1.1 reinoud udf_rw32(context.partitions[context.data_part]->start_loc); 2948 1.1 reinoud 2949 1.1 reinoud return 0; 2950 1.1 reinoud } 2951 1.1 reinoud 2952 1.1 reinoud 2953 1.1 reinoud static int 2954 1.1 reinoud udf_close_volume_vat(void) 2955 1.1 reinoud { 2956 1.1 reinoud int integrity_type; 2957 1.1 reinoud 2958 1.1 reinoud /* only write out when its open */ 2959 1.1 reinoud integrity_type = udf_rw32(context.logvol_integrity->integrity_type); 2960 1.1 reinoud if (integrity_type == UDF_INTEGRITY_CLOSED) 2961 1.1 reinoud return 0; 2962 1.1 reinoud 2963 1.1 reinoud if (!preen) 2964 1.1 reinoud printf("\n"); 2965 1.1 reinoud if (!ask(1, "Write out modifications")) 2966 1.1 reinoud return 0; 2967 1.1 reinoud 2968 1.1 reinoud /* writeout our VAT contents */ 2969 1.1 reinoud udf_allow_writing(); 2970 1.1 reinoud return udf_writeout_VAT(); 2971 1.1 reinoud } 2972 1.1 reinoud 2973 1.1 reinoud 2974 1.1 reinoud static int 2975 1.1 reinoud udf_close_volume(void) 2976 1.1 reinoud { 2977 1.1 reinoud struct part_desc *part; 2978 1.1 reinoud struct part_hdr_desc *phd; 2979 1.1 reinoud struct logvol_int_desc *lvid; 2980 1.1 reinoud struct udf_logvol_info *lvinfo; 2981 1.1 reinoud struct logvol_desc *logvol; 2982 1.1 reinoud uint32_t bitmap_len, bitmap_lb, bitmap_numlb; 2983 1.1 reinoud int i, equal, error; 2984 1.1 reinoud 2985 1.1 reinoud lvid = context.logvol_integrity; 2986 1.1 reinoud logvol = context.logical_vol; 2987 1.1 reinoud lvinfo = context.logvol_info; 2988 1.1 reinoud assert(lvid); 2989 1.1 reinoud assert(logvol); 2990 1.1 reinoud assert(lvinfo); 2991 1.1 reinoud 2992 1.1 reinoud /* check our highest unique id */ 2993 1.1 reinoud if (context.unique_id > udf_rw64(lvid->lvint_next_unique_id)) { 2994 1.3 martin pwarn("Last unique id updated from %" PRIi64 " to %" PRIi64 " : FIXED\n", 2995 1.1 reinoud udf_rw64(lvid->lvint_next_unique_id), 2996 1.1 reinoud context.unique_id); 2997 1.1 reinoud open_integrity = 1; 2998 1.1 reinoud } 2999 1.1 reinoud 3000 1.1 reinoud /* check file/directory counts */ 3001 1.1 reinoud if (context.num_files != udf_rw32(lvinfo->num_files)) { 3002 1.1 reinoud pwarn("Number of files corrected from %d to %d : FIXED\n", 3003 1.1 reinoud udf_rw32(lvinfo->num_files), 3004 1.1 reinoud context.num_files); 3005 1.1 reinoud open_integrity = 1; 3006 1.1 reinoud } 3007 1.1 reinoud if (context.num_directories != udf_rw32(lvinfo->num_directories)) { 3008 1.1 reinoud pwarn("Number of directories corrected from %d to %d : FIXED\n", 3009 1.1 reinoud udf_rw32(lvinfo->num_directories), 3010 1.1 reinoud context.num_directories); 3011 1.1 reinoud open_integrity = 1; 3012 1.1 reinoud } 3013 1.1 reinoud 3014 1.1 reinoud if (vat_writeout) 3015 1.1 reinoud open_integrity = 1; 3016 1.1 reinoud 3017 1.1 reinoud if (open_integrity) 3018 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_OPEN); 3019 1.1 reinoud 3020 1.1 reinoud if (context.format_flags & FORMAT_VAT) 3021 1.1 reinoud return udf_close_volume_vat(); 3022 1.1 reinoud 3023 1.1 reinoud /* adjust free space accounting! */ 3024 1.1 reinoud for (i = 0; i < UDF_PARTITIONS; i++) { 3025 1.1 reinoud part = context.partitions[i]; 3026 1.1 reinoud if (!part) 3027 1.1 reinoud continue; 3028 1.1 reinoud phd = &part->pd_part_hdr; 3029 1.1 reinoud bitmap_len = udf_rw32(phd->unalloc_space_bitmap.len); 3030 1.1 reinoud bitmap_lb = udf_rw32(phd->unalloc_space_bitmap.lb_num); 3031 1.1 reinoud 3032 1.1 reinoud if (bitmap_len == 0) { 3033 1.1 reinoud error = 0; 3034 1.1 reinoud continue; 3035 1.1 reinoud } 3036 1.1 reinoud 3037 1.1 reinoud equal = memcmp( recorded_part_unalloc_bits[i], 3038 1.1 reinoud context.part_unalloc_bits[i], 3039 1.1 reinoud bitmap_len) == 0; 3040 1.1 reinoud 3041 1.1 reinoud if (!equal || (context.part_free[i] != recorded_part_free[i])) { 3042 1.1 reinoud if (!equal) 3043 1.1 reinoud pwarn("Calculated bitmap for partition %d not equal " 3044 1.1 reinoud "to recorded one : FIXED\n", i); 3045 1.1 reinoud pwarn("Free space on partition %d corrected " 3046 1.1 reinoud "from %d to %d blocks : FIXED\n", i, 3047 1.1 reinoud recorded_part_free[i], 3048 1.1 reinoud context.part_free[i]); 3049 1.1 reinoud 3050 1.1 reinoud /* write out updated free space map */ 3051 1.1 reinoud pwarn("Updating unallocated bitmap for partition\n"); 3052 1.1 reinoud if (!preen) 3053 1.1 reinoud printf("Writing free space map " 3054 1.1 reinoud "for partition %d\n", i); 3055 1.1 reinoud error = 0; 3056 1.1 reinoud if (context.vtop_tp[i] == UDF_VTOP_TYPE_META) { 3057 1.1 reinoud if (context.meta_bitmap) { 3058 1.1 reinoud assert(i == context.metadata_part); 3059 1.1 reinoud error = udf_process_file( 3060 1.1 reinoud (union dscrptr *) context.meta_bitmap, 3061 1.1 reinoud context.data_part, 3062 1.1 reinoud (uint8_t **) &(context.part_unalloc_bits[i]), 3063 1.1 reinoud AD_SAVE_FILE, NULL); 3064 1.1 reinoud } 3065 1.1 reinoud } else { 3066 1.1 reinoud bitmap_numlb = udf_bytes_to_sectors(bitmap_len); 3067 1.1 reinoud error = udf_write_dscr_virt( 3068 1.1 reinoud (union dscrptr *) context.part_unalloc_bits[i], 3069 1.1 reinoud bitmap_lb, 3070 1.1 reinoud i, 3071 1.1 reinoud bitmap_numlb); 3072 1.1 reinoud } 3073 1.1 reinoud if (error) 3074 1.1 reinoud pwarn("Updating unallocated bitmap failed, " 3075 1.1 reinoud "continuing\n"); 3076 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_OPEN); 3077 1.1 reinoud } 3078 1.1 reinoud } 3079 1.1 reinoud 3080 1.1 reinoud /* write out the logical volume integrity sequence */ 3081 1.1 reinoud error = udf_writeout_lvint(); 3082 1.1 reinoud 3083 1.1 reinoud return error; 3084 1.1 reinoud } 3085 1.1 reinoud 3086 1.1 reinoud /* --------------------------------------------------------------------- */ 3087 1.1 reinoud 3088 1.1 reinoud /* 3089 1.1 reinoud * Main part of file system checking. 3090 1.1 reinoud * 3091 1.1 reinoud * Walk the entire directory tree and check all link counts and rebuild the 3092 1.1 reinoud * free space map (if present) on the go. 3093 1.1 reinoud */ 3094 1.1 reinoud 3095 1.1 reinoud static struct udf_fsck_node * 3096 1.1 reinoud udf_new_fsck_node(struct udf_fsck_node *parent, struct long_ad *loc, char *fname) 3097 1.1 reinoud { 3098 1.1 reinoud struct udf_fsck_node *this; 3099 1.1 reinoud this = calloc(1, sizeof(struct udf_fsck_node)); 3100 1.1 reinoud if (!this) 3101 1.1 reinoud return NULL; 3102 1.1 reinoud 3103 1.1 reinoud this->parent = parent; 3104 1.1 reinoud this->fname = strdup(fname); 3105 1.1 reinoud this->loc = *loc; 3106 1.1 reinoud this->fsck_flags = 0; 3107 1.1 reinoud 3108 1.1 reinoud this->link_count = 0; 3109 1.1 reinoud this->found_link_count = 0; 3110 1.1 reinoud 3111 1.1 reinoud return this; 3112 1.1 reinoud } 3113 1.1 reinoud 3114 1.1 reinoud 3115 1.1 reinoud static void 3116 1.1 reinoud udf_node_path_piece(char *pathname, struct udf_fsck_node *node) 3117 1.1 reinoud { 3118 1.1 reinoud if (node->parent) { 3119 1.1 reinoud udf_node_path_piece(pathname, node->parent); 3120 1.1 reinoud if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR) 3121 1.1 reinoud strcat(pathname, ""); 3122 1.1 reinoud else 3123 1.1 reinoud strcat(pathname, "/"); 3124 1.1 reinoud } 3125 1.1 reinoud strcat(pathname, node->fname); 3126 1.1 reinoud } 3127 1.1 reinoud 3128 1.1 reinoud 3129 1.1 reinoud static char * 3130 1.1 reinoud udf_node_path(struct udf_fsck_node *node) 3131 1.1 reinoud { 3132 1.1 reinoud static char pathname[MAXPATHLEN + 10]; 3133 1.1 reinoud 3134 1.1 reinoud strcpy(pathname, "`"); 3135 1.1 reinoud if (node->parent) 3136 1.1 reinoud udf_node_path_piece(pathname, node); 3137 1.1 reinoud else 3138 1.1 reinoud strcat(pathname, "/"); 3139 1.1 reinoud strcat(pathname, "'"); 3140 1.1 reinoud 3141 1.1 reinoud return pathname; 3142 1.1 reinoud } 3143 1.1 reinoud 3144 1.1 reinoud 3145 1.1 reinoud static void 3146 1.1 reinoud udf_recursive_keep(struct udf_fsck_node *node) 3147 1.1 reinoud { 3148 1.1 reinoud while (node->parent) { 3149 1.1 reinoud node = node->parent; 3150 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_KEEP; 3151 1.1 reinoud } 3152 1.1 reinoud } 3153 1.1 reinoud 3154 1.1 reinoud 3155 1.1 reinoud static int 3156 1.1 reinoud udf_quick_check_fids(struct udf_fsck_node *node, union dscrptr *dscr) 3157 1.1 reinoud { 3158 1.1 reinoud struct udf_fsck_fid_context fid_context; 3159 1.1 reinoud int error; 3160 1.1 reinoud 3161 1.1 reinoud fid_context.fid_offset = 0; 3162 1.1 reinoud fid_context.data_left = node->found.inf_len; 3163 1.1 reinoud error = udf_process_file(dscr, context.fids_part, 3164 1.1 reinoud &node->directory, 3165 1.1 reinoud AD_CHECK_FIDS, 3166 1.1 reinoud &fid_context); 3167 1.1 reinoud 3168 1.1 reinoud return error; 3169 1.1 reinoud } 3170 1.1 reinoud 3171 1.1 reinoud 3172 1.1 reinoud /* read descriptor at node's location */ 3173 1.1 reinoud static int 3174 1.1 reinoud udf_read_node_dscr(struct udf_fsck_node *node, union dscrptr **dscrptr) 3175 1.1 reinoud { 3176 1.1 reinoud *dscrptr = NULL; 3177 1.1 reinoud return udf_read_dscr_virt( 3178 1.1 reinoud udf_rw32(node->loc.loc.lb_num), 3179 1.1 reinoud udf_rw16(node->loc.loc.part_num), 3180 1.1 reinoud dscrptr); 3181 1.1 reinoud } 3182 1.1 reinoud 3183 1.1 reinoud 3184 1.1 reinoud static int 3185 1.1 reinoud udf_extract_node_info(struct udf_fsck_node *node, union dscrptr *dscr, 3186 1.1 reinoud int be_quiet) 3187 1.1 reinoud { 3188 1.1 reinoud struct icb_tag *icb = NULL; 3189 1.1 reinoud struct file_entry *fe = NULL; 3190 1.1 reinoud struct extfile_entry *efe = NULL; 3191 1.1 reinoud int ad_type, error; 3192 1.1 reinoud 3193 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) { 3194 1.1 reinoud fe = (struct file_entry *) dscr; 3195 1.1 reinoud icb = &fe->icbtag; 3196 1.1 reinoud node->declared.inf_len = udf_rw64(fe->inf_len); 3197 1.1 reinoud node->declared.obj_size = udf_rw64(fe->inf_len); 3198 1.1 reinoud node->declared.logblks_rec = udf_rw64(fe->logblks_rec); 3199 1.1 reinoud node->link_count = udf_rw16(fe->link_cnt); 3200 1.1 reinoud node->unique_id = udf_rw64(fe->unique_id); 3201 1.1 reinoud 3202 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */ 3203 1.1 reinoud //if (fe->unique_id == 33) { return ENOENT;} 3204 1.1 reinoud 3205 1.1 reinoud } 3206 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) { 3207 1.1 reinoud efe = (struct extfile_entry *) dscr; 3208 1.1 reinoud icb = &efe->icbtag; 3209 1.1 reinoud node->declared.inf_len = udf_rw64(efe->inf_len); 3210 1.1 reinoud node->declared.obj_size = udf_rw64(efe->obj_size); 3211 1.1 reinoud node->declared.logblks_rec = udf_rw64(efe->logblks_rec); 3212 1.1 reinoud node->link_count = udf_rw16(efe->link_cnt); 3213 1.1 reinoud node->unique_id = udf_rw64(efe->unique_id); 3214 1.1 reinoud node->streamdir_loc = efe->streamdir_icb; 3215 1.1 reinoud if (node->streamdir_loc.len) 3216 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_HAS_STREAM_DIR; 3217 1.1 reinoud 3218 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */ 3219 1.1 reinoud //if (efe->unique_id == 0x891) { return ENOENT;} 3220 1.1 reinoud 3221 1.1 reinoud } 3222 1.1 reinoud 3223 1.1 reinoud if (!fe && !efe) { 3224 1.1 reinoud //printf("NOT REFERENCING AN FE/EFE!\n"); 3225 1.1 reinoud return ENOENT; 3226 1.1 reinoud } 3227 1.1 reinoud 3228 1.1 reinoud if (node->unique_id >= context.unique_id) 3229 1.1 reinoud context.unique_id = node->unique_id+1; 3230 1.1 reinoud 3231 1.1 reinoud ad_type = udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 3232 1.1 reinoud if ((ad_type != UDF_ICB_INTERN_ALLOC) && 3233 1.1 reinoud (ad_type != UDF_ICB_SHORT_ALLOC) && 3234 1.1 reinoud (ad_type != UDF_ICB_LONG_ALLOC)) { 3235 1.1 reinoud pwarn("%s : unknown allocation type\n", 3236 1.1 reinoud udf_node_path(node)); 3237 1.1 reinoud return EINVAL; 3238 1.1 reinoud } 3239 1.1 reinoud 3240 1.1 reinoud bzero(&node->found, sizeof(node->found)); 3241 1.1 reinoud error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL, 3242 1.1 reinoud AD_GATHER_STATS, (void *) &node->found); 3243 1.1 reinoud 3244 1.1 reinoud switch (icb->file_type) { 3245 1.1 reinoud case UDF_ICB_FILETYPE_RANDOMACCESS : 3246 1.1 reinoud case UDF_ICB_FILETYPE_BLOCKDEVICE : 3247 1.1 reinoud case UDF_ICB_FILETYPE_CHARDEVICE : 3248 1.1 reinoud case UDF_ICB_FILETYPE_FIFO : 3249 1.1 reinoud case UDF_ICB_FILETYPE_SOCKET : 3250 1.1 reinoud case UDF_ICB_FILETYPE_SYMLINK : 3251 1.1 reinoud case UDF_ICB_FILETYPE_REALTIME : 3252 1.1 reinoud break; 3253 1.1 reinoud default: 3254 1.1 reinoud /* unknown or unsupported file type, TODO clearing? */ 3255 1.1 reinoud free(dscr); 3256 1.1 reinoud pwarn("%s : specification violation, unknown file type %d\n", 3257 1.1 reinoud udf_node_path(node), icb->file_type); 3258 1.1 reinoud return ENOENT; 3259 1.1 reinoud case UDF_ICB_FILETYPE_STREAMDIR : 3260 1.1 reinoud case UDF_ICB_FILETYPE_DIRECTORY : 3261 1.1 reinoud /* read in the directory contents */ 3262 1.1 reinoud error = udf_readin_file(dscr, udf_rw16(node->loc.loc.part_num), 3263 1.1 reinoud &node->directory, NULL); 3264 1.1 reinoud 3265 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */ 3266 1.1 reinoud //if (dscr->efe.unique_id == 109) node->directory[125] = 0xff; 3267 1.1 reinoud //if (dscr->efe.unique_id == 310) memset(node->directory+1024, 0, 300); 3268 1.1 reinoud 3269 1.1 reinoud if (error && !be_quiet) { 3270 1.1 reinoud pwarn("%s : directory has read errors\n", 3271 1.1 reinoud udf_node_path(node)); 3272 1.1 reinoud if (ask(0, "Directory could be fixed or cleared. " 3273 1.1 reinoud "Wipe defective directory")) { 3274 1.1 reinoud return ENOENT; 3275 1.1 reinoud } 3276 1.1 reinoud udf_recursive_keep(node); 3277 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR; 3278 1.1 reinoud } 3279 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_DIRECTORY; 3280 1.1 reinoud error = udf_quick_check_fids(node, dscr); 3281 1.1 reinoud if (error) { 3282 1.1 reinoud if (!(node->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR)) 3283 1.1 reinoud pwarn("%s : directory file entries need repair\n", 3284 1.1 reinoud udf_node_path(node)); 3285 1.1 reinoud udf_recursive_keep(node); 3286 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR; 3287 1.1 reinoud } 3288 1.1 reinoud } 3289 1.1 reinoud 3290 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */ 3291 1.1 reinoud //if (fe->unique_id == 0) node->link_count++; 3292 1.1 reinoud //if (efe->unique_id == 0) node->link_count++; 3293 1.1 reinoud //if (efe->unique_id == 772) { node->declared.inf_len += 205; node->declared.obj_size -= 0; } 3294 1.1 reinoud 3295 1.1 reinoud return 0; 3296 1.1 reinoud } 3297 1.1 reinoud 3298 1.1 reinoud 3299 1.1 reinoud static void 3300 1.1 reinoud udf_fixup_lengths_pass1(struct udf_fsck_node *node, union dscrptr *dscr) 3301 1.1 reinoud { 3302 1.1 reinoud int64_t diff; 3303 1.1 reinoud 3304 1.1 reinoud /* file length check */ 3305 1.1 reinoud diff = node->found.inf_len - node->declared.inf_len; 3306 1.1 reinoud if (diff) { 3307 1.1 reinoud pwarn("%s : recorded information length incorrect: " 3308 1.3 martin "%" PRIu64 " instead of declared %" PRIu64 "\n", 3309 1.1 reinoud udf_node_path(node), 3310 1.1 reinoud node->found.inf_len, node->declared.inf_len); 3311 1.1 reinoud node->declared.inf_len = node->found.inf_len; 3312 1.1 reinoud udf_recursive_keep(node); 3313 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_DIRTY; 3314 1.1 reinoud } 3315 1.1 reinoud 3316 1.1 reinoud /* recorded logical blocks count check */ 3317 1.1 reinoud diff = node->found.logblks_rec - node->declared.logblks_rec; 3318 1.1 reinoud if (diff) { 3319 1.1 reinoud pwarn("%s : logical blocks recorded incorrect: " 3320 1.3 martin "%" PRIu64 " instead of declared %" PRIu64 ", fixing\n", 3321 1.1 reinoud udf_node_path(node), 3322 1.1 reinoud node->found.logblks_rec, node->declared.logblks_rec); 3323 1.1 reinoud node->declared.logblks_rec = node->found.logblks_rec; 3324 1.1 reinoud udf_recursive_keep(node); 3325 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_DIRTY; 3326 1.1 reinoud } 3327 1.1 reinoud 3328 1.1 reinoud /* tally object sizes for streamdirs */ 3329 1.1 reinoud node->found.obj_size = node->found.inf_len; 3330 1.1 reinoud if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_ENTRY) { 3331 1.1 reinoud assert(node->parent); /* streamdir itself */ 3332 1.1 reinoud if (node->parent->parent) 3333 1.1 reinoud node->parent->parent->found.obj_size += 3334 1.1 reinoud node->found.inf_len; 3335 1.1 reinoud } 3336 1.1 reinoud 3337 1.1 reinoud /* check descriptor CRC length */ 3338 1.1 reinoud if (udf_rw16(dscr->tag.desc_crc_len) != 3339 1.1 reinoud udf_tagsize(dscr, 1) - sizeof(struct desc_tag)) { 3340 1.1 reinoud pwarn("%s : node file descriptor CRC length mismatch; " 3341 1.3 martin "%d declared, %zu\n", 3342 1.1 reinoud udf_node_path(node), udf_rw16(dscr->tag.desc_crc_len), 3343 1.1 reinoud udf_tagsize(dscr, 1) - sizeof(struct desc_tag)); 3344 1.1 reinoud udf_recursive_keep(node); 3345 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_DIRTY; 3346 1.1 reinoud } 3347 1.1 reinoud } 3348 1.1 reinoud 3349 1.1 reinoud 3350 1.1 reinoud static void 3351 1.1 reinoud udf_node_pass1_add_entry(struct udf_fsck_node *node, 3352 1.1 reinoud struct fileid_desc *fid, struct dirent *dirent) 3353 1.1 reinoud { 3354 1.1 reinoud struct udf_fsck_node *leaf_node; 3355 1.1 reinoud int entry; 3356 1.1 reinoud 3357 1.1 reinoud /* skip deleted FID entries */ 3358 1.1 reinoud if (fid->file_char & UDF_FILE_CHAR_DEL) 3359 1.1 reinoud return; 3360 1.1 reinoud 3361 1.1 reinoud if (udf_rw32(fid->icb.loc.lb_num) == 0) { 3362 1.1 reinoud pwarn("%s : FileID entry `%s` has invalid location\n", 3363 1.1 reinoud udf_node_path(node), dirent->d_name); 3364 1.1 reinoud udf_recursive_keep(node); 3365 1.1 reinoud if (node->parent) 3366 1.1 reinoud node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR; 3367 1.1 reinoud return; 3368 1.1 reinoud } 3369 1.1 reinoud 3370 1.1 reinoud /* increase parent link count */ 3371 1.1 reinoud if (fid->file_char & UDF_FILE_CHAR_PAR) { 3372 1.1 reinoud if (node->parent) 3373 1.1 reinoud node->parent->found_link_count++; 3374 1.1 reinoud return; 3375 1.1 reinoud } 3376 1.1 reinoud 3377 1.1 reinoud /* lookup if we already know this node */ 3378 1.1 reinoud leaf_node = udf_node_lookup(&fid->icb); 3379 1.1 reinoud if (leaf_node) { 3380 1.1 reinoud /* got a hard link! */ 3381 1.1 reinoud leaf_node->found_link_count++; 3382 1.1 reinoud return; 3383 1.1 reinoud } 3384 1.1 reinoud 3385 1.1 reinoud /* create new node */ 3386 1.1 reinoud leaf_node = udf_new_fsck_node( 3387 1.1 reinoud node, &fid->icb, dirent->d_name); 3388 1.1 reinoud if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR) 3389 1.1 reinoud leaf_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_ENTRY; 3390 1.1 reinoud 3391 1.1 reinoud TAILQ_INSERT_TAIL(&fs_nodes, leaf_node, next); 3392 1.1 reinoud entry = udf_calc_node_hash(&fid->icb); 3393 1.1 reinoud LIST_INSERT_HEAD(&fs_nodes_hash[entry], leaf_node, next_hash); 3394 1.1 reinoud } 3395 1.1 reinoud 3396 1.1 reinoud 3397 1.1 reinoud static void 3398 1.1 reinoud udf_node_pass1_add_streamdir_entry(struct udf_fsck_node *node) 3399 1.1 reinoud { 3400 1.1 reinoud struct udf_fsck_node *leaf_node; 3401 1.1 reinoud int entry; 3402 1.1 reinoud 3403 1.1 reinoud /* check for recursion */ 3404 1.1 reinoud if (node->fsck_flags & FSCK_NODE_FLAG_STREAM) { 3405 1.1 reinoud /* recursive streams are not allowed by spec */ 3406 1.1 reinoud pwarn("%s : specification violation, recursive stream dir\n", 3407 1.1 reinoud udf_node_path(node)); 3408 1.1 reinoud udf_recursive_keep(node); 3409 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_WIPE_STREAM_DIR; 3410 1.1 reinoud return; 3411 1.1 reinoud } 3412 1.1 reinoud 3413 1.1 reinoud /* lookup if we already know this node */ 3414 1.1 reinoud leaf_node = udf_node_lookup(&node->streamdir_loc); 3415 1.1 reinoud if (leaf_node) { 3416 1.1 reinoud pwarn("%s : specification violation, hardlinked streamdir\n", 3417 1.1 reinoud udf_node_path(leaf_node)); 3418 1.1 reinoud udf_recursive_keep(node); 3419 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_WIPE_STREAM_DIR; 3420 1.1 reinoud return; 3421 1.1 reinoud } 3422 1.1 reinoud 3423 1.1 reinoud /* create new node */ 3424 1.1 reinoud leaf_node = udf_new_fsck_node( 3425 1.1 reinoud node, &node->streamdir_loc, strdup("")); 3426 1.1 reinoud leaf_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_DIR; 3427 1.1 reinoud 3428 1.1 reinoud /* streamdirs have link count 0 : ECMA 4/14.9.6 */ 3429 1.1 reinoud leaf_node->found_link_count--; 3430 1.1 reinoud 3431 1.1 reinoud /* insert in to lists */ 3432 1.1 reinoud TAILQ_INSERT_TAIL(&fs_nodes, leaf_node, next); 3433 1.1 reinoud entry = udf_calc_node_hash(&node->streamdir_loc); 3434 1.1 reinoud LIST_INSERT_HEAD(&fs_nodes_hash[entry], leaf_node, next_hash); 3435 1.1 reinoud } 3436 1.1 reinoud 3437 1.1 reinoud 3438 1.1 reinoud static int 3439 1.1 reinoud udf_process_node_pass1(struct udf_fsck_node *node, union dscrptr *dscr) 3440 1.1 reinoud { 3441 1.1 reinoud struct fileid_desc *fid; 3442 1.1 reinoud struct dirent dirent; 3443 1.1 reinoud struct charspec osta_charspec; 3444 1.1 reinoud int64_t fpos, new_length, rest_len; 3445 1.1 reinoud uint32_t fid_len; 3446 1.1 reinoud uint8_t *bpos; 3447 1.1 reinoud int isdir; 3448 1.1 reinoud int error; 3449 1.1 reinoud 3450 1.1 reinoud isdir = node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY; 3451 1.1 reinoud 3452 1.1 reinoud /* keep link count */ 3453 1.1 reinoud node->found_link_count++; 3454 1.1 reinoud 3455 1.1 reinoud if (isdir) { 3456 1.1 reinoud assert(node->directory); 3457 1.1 reinoud udf_rebuild_fid_stream(node, &new_length); 3458 1.1 reinoud node->found.inf_len = new_length; 3459 1.1 reinoud rest_len = new_length; 3460 1.1 reinoud } 3461 1.1 reinoud 3462 1.1 reinoud udf_fixup_lengths_pass1(node, dscr); 3463 1.1 reinoud 3464 1.1 reinoud /* check UniqueID */ 3465 1.1 reinoud if (node->parent) { 3466 1.1 reinoud if (node->fsck_flags & FSCK_NODE_FLAG_STREAM) { 3467 1.1 reinoud 3468 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */ 3469 1.1 reinoud //node->unique_id = 0xdeadbeefcafe; 3470 1.1 reinoud 3471 1.1 reinoud if (node->unique_id != node->parent->unique_id) { 3472 1.1 reinoud pwarn("%s : stream file/dir UniqueID mismatch " 3473 1.1 reinoud "with parent\n", 3474 1.1 reinoud udf_node_path(node)); 3475 1.1 reinoud /* do the work here prematurely for our siblings */ 3476 1.1 reinoud udf_recursive_keep(node); 3477 1.1 reinoud node->unique_id = node->parent->unique_id; 3478 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_COPY_PARENT_ID | 3479 1.1 reinoud FSCK_NODE_FLAG_DIRTY; 3480 1.1 reinoud assert(node->parent); 3481 1.1 reinoud node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR; 3482 1.1 reinoud } 3483 1.1 reinoud } else if (node->unique_id < 16) { 3484 1.1 reinoud pwarn("%s : file has bad UniqueID\n", 3485 1.1 reinoud udf_node_path(node)); 3486 1.1 reinoud udf_recursive_keep(node); 3487 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_NEW_UNIQUE_ID; 3488 1.1 reinoud assert(node->parent); 3489 1.1 reinoud node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR; 3490 1.1 reinoud } 3491 1.1 reinoud } else { 3492 1.1 reinoud /* rootdir */ 3493 1.1 reinoud if (node->unique_id != 0) { 3494 1.1 reinoud pwarn("%s : has bad UniqueID, has to be zero\n", 3495 1.1 reinoud udf_node_path(node)); 3496 1.1 reinoud udf_recursive_keep(node); 3497 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR; 3498 1.1 reinoud } 3499 1.1 reinoud } 3500 1.1 reinoud 3501 1.1 reinoud /* add streamdir if present */ 3502 1.1 reinoud if (node->fsck_flags & FSCK_NODE_FLAG_HAS_STREAM_DIR) 3503 1.1 reinoud udf_node_pass1_add_streamdir_entry(node); 3504 1.1 reinoud 3505 1.1 reinoud /* add all children */ 3506 1.1 reinoud if (isdir) { 3507 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_PAR_NOT_FOUND; 3508 1.1 reinoud rest_len = node->found.inf_len; 3509 1.1 reinoud 3510 1.2 wiz /* walk through all our FIDs in the directory stream */ 3511 1.1 reinoud bpos = node->directory; 3512 1.1 reinoud fpos = 0; 3513 1.1 reinoud while (rest_len > 0) { 3514 1.1 reinoud fid = (struct fileid_desc *) bpos; 3515 1.1 reinoud fid_len = udf_fidsize(fid); 3516 1.1 reinoud 3517 1.1 reinoud /* get printable name */ 3518 1.1 reinoud memset(&dirent, 0, sizeof(dirent)); 3519 1.1 reinoud udf_osta_charset(&osta_charspec); 3520 1.1 reinoud udf_to_unix_name(dirent.d_name, NAME_MAX, 3521 1.1 reinoud (char *) fid->data + udf_rw16(fid->l_iu), fid->l_fi, 3522 1.1 reinoud &osta_charspec); 3523 1.1 reinoud dirent.d_namlen = strlen(dirent.d_name); 3524 1.1 reinoud 3525 1.1 reinoud /* '..' has no name, so provide one */ 3526 1.1 reinoud if (fid->file_char & UDF_FILE_CHAR_PAR) { 3527 1.1 reinoud strcpy(dirent.d_name, ".."); 3528 1.1 reinoud node->fsck_flags &= ~FSCK_NODE_FLAG_PAR_NOT_FOUND; 3529 1.1 reinoud } 3530 1.1 reinoud 3531 1.1 reinoud udf_node_pass1_add_entry(node, fid, &dirent); 3532 1.1 reinoud 3533 1.1 reinoud fpos += fid_len; 3534 1.1 reinoud bpos += fid_len; 3535 1.1 reinoud rest_len -= fid_len; 3536 1.1 reinoud } 3537 1.1 reinoud } 3538 1.1 reinoud 3539 1.1 reinoud error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL, 3540 1.1 reinoud AD_CHECK_USED, node); 3541 1.1 reinoud if (error) { 3542 1.1 reinoud pwarn("%s : internal error: checking for being allocated shouldn't fail\n", 3543 1.1 reinoud udf_node_path(node)); 3544 1.1 reinoud return EINVAL; 3545 1.1 reinoud } 3546 1.1 reinoud /* file/directory is OK and referenced as its size won't change */ 3547 1.1 reinoud error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL, 3548 1.1 reinoud AD_MARK_AS_USED, NULL); 3549 1.1 reinoud if (error) { 3550 1.1 reinoud pwarn("%s : internal error: marking allocated shouldn't fail\n", 3551 1.1 reinoud udf_node_path(node)); 3552 1.1 reinoud return EINVAL; 3553 1.1 reinoud } 3554 1.7 reinoud (void) fpos; 3555 1.1 reinoud return 0; 3556 1.1 reinoud } 3557 1.1 reinoud 3558 1.1 reinoud 3559 1.1 reinoud static void 3560 1.1 reinoud udf_node_pass3_repairdir(struct udf_fsck_node *node, union dscrptr *dscr) 3561 1.1 reinoud { 3562 1.1 reinoud struct fileid_desc *fid, *last_empty_fid; 3563 1.1 reinoud struct udf_fsck_node *file_node; 3564 1.1 reinoud struct udf_fsck_fid_context fid_context; 3565 1.1 reinoud struct dirent dirent; 3566 1.1 reinoud struct charspec osta_charspec; 3567 1.1 reinoud int64_t fpos, rest_len; 3568 1.1 reinoud uint32_t fid_len; 3569 1.1 reinoud uint8_t *bpos; 3570 1.1 reinoud int parent_missing; 3571 1.1 reinoud int error; 3572 1.1 reinoud 3573 1.1 reinoud pwarn("%s : fixing up directory\n", udf_node_path(node)); 3574 1.1 reinoud assert(node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY); 3575 1.1 reinoud 3576 1.1 reinoud rest_len = node->found.inf_len; 3577 1.1 reinoud 3578 1.1 reinoud udf_osta_charset(&osta_charspec); 3579 1.1 reinoud bpos = node->directory; 3580 1.1 reinoud fpos = 0; 3581 1.1 reinoud parent_missing = (node->fsck_flags & FSCK_NODE_FLAG_PAR_NOT_FOUND)? 1:0; 3582 1.1 reinoud 3583 1.1 reinoud last_empty_fid = NULL; 3584 1.1 reinoud while (rest_len > 0) { 3585 1.1 reinoud fid = (struct fileid_desc *) bpos; 3586 1.1 reinoud fid_len = udf_fidsize(fid); 3587 1.1 reinoud 3588 1.1 reinoud /* get printable name */ 3589 1.1 reinoud memset(&dirent, 0, sizeof(dirent)); 3590 1.1 reinoud udf_to_unix_name(dirent.d_name, NAME_MAX, 3591 1.1 reinoud (char *) fid->data + udf_rw16(fid->l_iu), fid->l_fi, 3592 1.1 reinoud &osta_charspec); 3593 1.1 reinoud dirent.d_namlen = strlen(dirent.d_name); 3594 1.1 reinoud 3595 1.1 reinoud /* '..' has no name, so provide one */ 3596 1.1 reinoud if (fid->file_char & UDF_FILE_CHAR_PAR) { 3597 1.1 reinoud strcpy(dirent.d_name, ".."); 3598 1.1 reinoud } 3599 1.1 reinoud 3600 1.1 reinoud /* only look up when not deleted */ 3601 1.1 reinoud file_node = NULL; 3602 1.1 reinoud if ((fid->file_char & UDF_FILE_CHAR_DEL) == 0) 3603 1.1 reinoud file_node = udf_node_lookup(&fid->icb); 3604 1.1 reinoud 3605 1.1 reinoud /* if found */ 3606 1.1 reinoud if (file_node) { 3607 1.1 reinoud /* delete files which couldn't be found */ 3608 1.1 reinoud if (file_node && (file_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)) { 3609 1.1 reinoud fid->file_char |= UDF_FILE_CHAR_DEL; 3610 1.1 reinoud memset(&fid->icb, 0, sizeof(struct long_ad)); 3611 1.1 reinoud } 3612 1.1 reinoud 3613 1.1 reinoud /* fix up FID UniqueID errors */ 3614 1.1 reinoud if (fid->icb.longad_uniqueid != file_node->unique_id) 3615 1.1 reinoud fid->icb.longad_uniqueid = udf_rw64(file_node->unique_id); 3616 1.1 reinoud } else { 3617 1.1 reinoud /* just mark it deleted if not found */ 3618 1.1 reinoud fid->file_char |= UDF_FILE_CHAR_DEL; 3619 1.1 reinoud } 3620 1.1 reinoud 3621 1.1 reinoud if (fid->file_char & UDF_FILE_CHAR_DEL) { 3622 1.1 reinoud memset(&fid->icb, 0 , sizeof(struct long_ad)); 3623 1.1 reinoud if (context.dscrver == 2) { 3624 1.1 reinoud uint8_t *cpos; 3625 1.1 reinoud /* compression IDs are preserved */ 3626 1.1 reinoud cpos = (fid->data + udf_rw16(fid->l_iu)); 3627 1.1 reinoud if (*cpos == 254) 3628 1.1 reinoud *cpos = 8; 3629 1.1 reinoud if (*cpos == 255) 3630 1.1 reinoud *cpos = 16; 3631 1.1 reinoud } 3632 1.1 reinoud } 3633 1.1 reinoud 3634 1.1 reinoud fpos += fid_len; 3635 1.1 reinoud bpos += fid_len; 3636 1.1 reinoud rest_len -= fid_len; 3637 1.1 reinoud assert(rest_len >= 0); 3638 1.1 reinoud } 3639 1.1 reinoud if (parent_missing) { 3640 1.1 reinoud /* this should be valid or we're in LALA land */ 3641 1.1 reinoud assert(last_empty_fid); 3642 1.1 reinoud pwarn("%s : implementation limit, can't fix up missing parent node yet!\n", 3643 1.1 reinoud udf_node_path(node)); 3644 1.1 reinoud } 3645 1.1 reinoud 3646 1.1 reinoud node->fsck_flags |= FSCK_NODE_FLAG_DIRTY; 3647 1.1 reinoud 3648 1.1 reinoud fid_context.fid_offset = 0; 3649 1.1 reinoud fid_context.data_left = node->found.inf_len; 3650 1.1 reinoud error = udf_process_file(dscr, context.fids_part, 3651 1.1 reinoud &node->directory, 3652 1.1 reinoud AD_ADJUST_FIDS | AD_SAVE_FILE, 3653 1.1 reinoud &fid_context); 3654 1.1 reinoud if (error) 3655 1.1 reinoud pwarn("Failed to write out directory!\n"); 3656 1.7 reinoud (void) fpos; 3657 1.1 reinoud } 3658 1.1 reinoud 3659 1.1 reinoud 3660 1.1 reinoud static void 3661 1.1 reinoud udf_node_pass3_writeout_update(struct udf_fsck_node *node, union dscrptr *dscr) 3662 1.1 reinoud { 3663 1.1 reinoud struct file_entry *fe = NULL; 3664 1.1 reinoud struct extfile_entry *efe = NULL; 3665 1.12 reinoud int crc_len, error; 3666 1.1 reinoud 3667 1.1 reinoud vat_writeout = 1; 3668 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) { 3669 1.1 reinoud fe = (struct file_entry *) dscr; 3670 1.1 reinoud fe->inf_len = udf_rw64(node->declared.inf_len); 3671 1.1 reinoud fe->logblks_rec = udf_rw64(node->declared.logblks_rec); 3672 1.1 reinoud fe->link_cnt = udf_rw16(node->link_count); 3673 1.1 reinoud fe->unique_id = udf_rw64(node->unique_id); 3674 1.1 reinoud } 3675 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) { 3676 1.1 reinoud efe = (struct extfile_entry *) dscr; 3677 1.1 reinoud efe->inf_len = udf_rw64(node->declared.inf_len); 3678 1.1 reinoud efe->obj_size = udf_rw64(node->declared.obj_size); 3679 1.1 reinoud efe->logblks_rec = udf_rw64(node->declared.logblks_rec); 3680 1.1 reinoud efe->link_cnt = udf_rw16(node->link_count); 3681 1.1 reinoud efe->unique_id = udf_rw64(node->unique_id); 3682 1.1 reinoud /* streamdir directly cleared in dscr */ 3683 1.1 reinoud } 3684 1.1 reinoud 3685 1.1 reinoud /* fixup CRC length (if needed) */ 3686 1.12 reinoud crc_len = udf_tagsize(dscr, 1) - sizeof(struct desc_tag); 3687 1.12 reinoud dscr->tag.desc_crc_len = udf_rw16(crc_len); 3688 1.1 reinoud 3689 1.1 reinoud pwarn("%s : updating node\n", udf_node_path(node)); 3690 1.1 reinoud error = udf_write_dscr_virt(dscr, udf_rw32(node->loc.loc.lb_num), 3691 1.1 reinoud udf_rw16(node->loc.loc.part_num), 1); 3692 1.1 reinoud udf_shadow_VAT_in_use(&node->loc); 3693 1.1 reinoud if (error) 3694 1.1 reinoud pwarn("%s failed\n", __func__); 3695 1.1 reinoud } 3696 1.1 reinoud 3697 1.1 reinoud 3698 1.1 reinoud static void 3699 1.1 reinoud udf_create_new_space_bitmaps_and_reset_freespace(void) 3700 1.1 reinoud { 3701 1.1 reinoud struct space_bitmap_desc *sbd, *new_sbd; 3702 1.1 reinoud struct part_desc *part; 3703 1.1 reinoud struct part_hdr_desc *phd; 3704 1.1 reinoud uint32_t bitmap_len, bitmap_lb, bitmap_numlb; 3705 1.1 reinoud uint32_t cnt; 3706 1.1 reinoud int i, p, dscr_size; 3707 1.1 reinoud int error; 3708 1.1 reinoud 3709 1.1 reinoud /* copy recorded freespace info and clear counters */ 3710 1.1 reinoud for (i = 0; i < UDF_PARTITIONS; i++) { 3711 1.1 reinoud recorded_part_free[i] = context.part_free[i]; 3712 1.1 reinoud context.part_free[i] = context.part_size[i]; 3713 1.1 reinoud } 3714 1.1 reinoud 3715 1.1 reinoud /* clone existing bitmaps */ 3716 1.1 reinoud for (i = 0; i < UDF_PARTITIONS; i++) { 3717 1.1 reinoud sbd = context.part_unalloc_bits[i]; 3718 1.1 reinoud recorded_part_unalloc_bits[i] = sbd; 3719 1.1 reinoud if (sbd == NULL) 3720 1.1 reinoud continue; 3721 1.1 reinoud dscr_size = udf_tagsize((union dscrptr *) sbd, 3722 1.1 reinoud context.sector_size); 3723 1.1 reinoud new_sbd = calloc(1, dscr_size); 3724 1.1 reinoud memcpy(new_sbd, sbd, sizeof(struct space_bitmap_desc)-1); 3725 1.1 reinoud 3726 1.1 reinoud /* fill space with 0xff to indicate free */ 3727 1.1 reinoud for (cnt = 0; cnt < udf_rw32(sbd->num_bytes); cnt++) 3728 1.1 reinoud new_sbd->data[cnt] = 0xff; 3729 1.1 reinoud 3730 1.1 reinoud context.part_unalloc_bits[i] = new_sbd; 3731 1.1 reinoud } 3732 1.1 reinoud 3733 1.1 reinoud /* allocate the space bitmaps themselves (normally one) */ 3734 1.1 reinoud for (i = 0; i < UDF_PARTITIONS; i++) { 3735 1.1 reinoud part = context.partitions[i]; 3736 1.1 reinoud if (!part) 3737 1.1 reinoud continue; 3738 1.1 reinoud 3739 1.1 reinoud phd = &part->pd_part_hdr; 3740 1.1 reinoud bitmap_len = udf_rw32(phd->unalloc_space_bitmap.len); 3741 1.1 reinoud bitmap_lb = udf_rw32(phd->unalloc_space_bitmap.lb_num); 3742 1.1 reinoud if (bitmap_len == 0) 3743 1.1 reinoud continue; 3744 1.1 reinoud 3745 1.1 reinoud bitmap_numlb = udf_bytes_to_sectors(bitmap_len); 3746 1.1 reinoud sbd = context.part_unalloc_bits[i]; 3747 1.1 reinoud assert(sbd); 3748 1.1 reinoud 3749 1.1 reinoud udf_mark_allocated(bitmap_lb, context.vtop[i], bitmap_numlb); 3750 1.1 reinoud } 3751 1.1 reinoud 3752 1.1 reinoud /* special case for metadata partition */ 3753 1.1 reinoud if (context.format_flags & FORMAT_META) { 3754 1.1 reinoud i = context.metadata_part; 3755 1.1 reinoud p = context.vtop[i]; 3756 1.1 reinoud assert(context.vtop_tp[i] == UDF_VTOP_TYPE_META); 3757 1.1 reinoud error = udf_process_file((union dscrptr *) context.meta_file, 3758 1.1 reinoud p, NULL, AD_MARK_AS_USED, NULL); 3759 1.1 reinoud error = udf_process_file((union dscrptr *) context.meta_mirror, 3760 1.1 reinoud p, NULL, AD_MARK_AS_USED, NULL); 3761 1.1 reinoud if (context.meta_bitmap) { 3762 1.1 reinoud error = udf_process_file( 3763 1.1 reinoud (union dscrptr *) context.meta_bitmap, 3764 1.1 reinoud p, NULL, AD_MARK_AS_USED, NULL); 3765 1.1 reinoud assert(error == 0); 3766 1.1 reinoud } 3767 1.1 reinoud } 3768 1.1 reinoud 3769 1.1 reinoud /* mark fsd allocation ! */ 3770 1.1 reinoud udf_mark_allocated(udf_rw32(context.fileset_desc->tag.tag_loc), 3771 1.1 reinoud context.metadata_part, 1); 3772 1.1 reinoud } 3773 1.1 reinoud 3774 1.1 reinoud 3775 1.1 reinoud static void 3776 1.1 reinoud udf_shadow_VAT_in_use(struct long_ad *loc) 3777 1.1 reinoud { 3778 1.1 reinoud uint32_t i; 3779 1.1 reinoud uint8_t *vat_pos, *shadow_vat_pos; 3780 1.1 reinoud 3781 1.1 reinoud if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT) 3782 1.1 reinoud return; 3783 1.1 reinoud 3784 1.1 reinoud i = udf_rw32(loc->loc.lb_num); 3785 1.1 reinoud vat_pos = context.vat_contents + context.vat_start + i*4; 3786 1.1 reinoud shadow_vat_pos = shadow_vat_contents + context.vat_start + i*4; 3787 1.1 reinoud /* keeping endian */ 3788 1.1 reinoud *(uint32_t *) shadow_vat_pos = *(uint32_t *) vat_pos; 3789 1.1 reinoud } 3790 1.1 reinoud 3791 1.1 reinoud 3792 1.1 reinoud static void 3793 1.1 reinoud udf_create_shadow_VAT(void) 3794 1.1 reinoud { 3795 1.1 reinoud struct long_ad fsd_loc; 3796 1.1 reinoud uint32_t vat_entries, i; 3797 1.1 reinoud uint8_t *vat_pos; 3798 1.1 reinoud 3799 1.1 reinoud if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT) 3800 1.1 reinoud return; 3801 1.1 reinoud 3802 1.1 reinoud shadow_vat_contents = calloc(1, context.vat_allocated); 3803 1.1 reinoud assert(shadow_vat_contents); 3804 1.1 reinoud memcpy(shadow_vat_contents, context.vat_contents, context.vat_size); 3805 1.1 reinoud 3806 1.1 reinoud vat_entries = (context.vat_size - context.vat_start)/4; 3807 1.1 reinoud for (i = 0; i < vat_entries; i++) { 3808 1.1 reinoud vat_pos = shadow_vat_contents + context.vat_start + i*4; 3809 1.1 reinoud *(uint32_t *) vat_pos = udf_rw32(0xffffffff); 3810 1.1 reinoud } 3811 1.1 reinoud 3812 1.1 reinoud /* 3813 1.1 reinoud * Record our FSD in this shadow VAT since its the only one outside 3814 1.1 reinoud * the nodes. 3815 1.1 reinoud */ 3816 1.1 reinoud memset(&fsd_loc, 0, sizeof(struct long_ad)); 3817 1.1 reinoud fsd_loc.loc.lb_num = context.fileset_desc->tag.tag_loc; 3818 1.1 reinoud udf_shadow_VAT_in_use(&fsd_loc); 3819 1.1 reinoud } 3820 1.1 reinoud 3821 1.1 reinoud 3822 1.1 reinoud static void 3823 1.1 reinoud udf_check_shadow_VAT(void) 3824 1.1 reinoud { 3825 1.1 reinoud uint32_t vat_entries, i; 3826 1.1 reinoud uint8_t *vat_pos, *shadow_vat_pos; 3827 1.1 reinoud int difference = 0; 3828 1.1 reinoud 3829 1.1 reinoud if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT) 3830 1.1 reinoud return; 3831 1.1 reinoud 3832 1.1 reinoud vat_entries = (context.vat_size - context.vat_start)/4; 3833 1.1 reinoud for (i = 0; i < vat_entries; i++) { 3834 1.1 reinoud vat_pos = context.vat_contents + context.vat_start + i*4; 3835 1.1 reinoud shadow_vat_pos = shadow_vat_contents + context.vat_start + i*4; 3836 1.1 reinoud if (*(uint32_t *) vat_pos != *(uint32_t *) shadow_vat_pos) { 3837 1.1 reinoud difference++; 3838 1.1 reinoud } 3839 1.1 reinoud } 3840 1.1 reinoud memcpy(context.vat_contents, shadow_vat_contents, context.vat_size); 3841 1.1 reinoud if (difference) { 3842 1.1 reinoud if (!preen) 3843 1.1 reinoud printf("\t\t"); 3844 1.1 reinoud pwarn("%d unused VAT entries cleaned\n", difference); 3845 1.1 reinoud vat_writeout = 1; 3846 1.1 reinoud } 3847 1.1 reinoud } 3848 1.1 reinoud 3849 1.1 reinoud 3850 1.1 reinoud static int 3851 1.1 reinoud udf_check_directory_tree(void) 3852 1.1 reinoud { 3853 1.1 reinoud union dscrptr *dscr; 3854 1.1 reinoud struct udf_fsck_node *root_node, *sys_stream_node; 3855 1.1 reinoud struct udf_fsck_node *cur_node, *next_node; 3856 1.1 reinoud struct long_ad root_icb, sys_stream_icb; 3857 1.1 reinoud bool dont_repair; 3858 1.1 reinoud int entry, error; 3859 1.1 reinoud 3860 1.1 reinoud assert(TAILQ_EMPTY(&fs_nodes)); 3861 1.1 reinoud 3862 1.1 reinoud /* (re)init queues and hash lists */ 3863 1.1 reinoud TAILQ_INIT(&fs_nodes); 3864 1.1 reinoud TAILQ_INIT(&fsck_overlaps); 3865 1.1 reinoud for (int i = 0; i < HASH_HASHSIZE; i++) 3866 1.1 reinoud LIST_INIT(&fs_nodes_hash[i]); 3867 1.1 reinoud 3868 1.1 reinoud /* create a new empty copy of the space bitmaps */ 3869 1.1 reinoud udf_create_new_space_bitmaps_and_reset_freespace(); 3870 1.1 reinoud udf_create_shadow_VAT(); 3871 1.1 reinoud 3872 1.1 reinoud /* start from the root */ 3873 1.1 reinoud root_icb = context.fileset_desc->rootdir_icb; 3874 1.1 reinoud sys_stream_icb = context.fileset_desc->streamdir_icb; 3875 1.1 reinoud 3876 1.1 reinoud root_node = udf_new_fsck_node(NULL, &root_icb, strdup("")); 3877 1.1 reinoud assert(root_node); 3878 1.1 reinoud TAILQ_INSERT_TAIL(&fs_nodes, root_node, next); 3879 1.1 reinoud entry = udf_calc_node_hash(&root_node->loc); 3880 1.1 reinoud LIST_INSERT_HEAD(&fs_nodes_hash[entry], root_node, next_hash); 3881 1.1 reinoud 3882 1.1 reinoud sys_stream_node = NULL; 3883 1.1 reinoud if (sys_stream_icb.len) { 3884 1.1 reinoud sys_stream_node = udf_new_fsck_node(NULL, &sys_stream_icb, strdup("#")); 3885 1.1 reinoud assert(sys_stream_node); 3886 1.1 reinoud sys_stream_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_DIR; 3887 1.1 reinoud 3888 1.1 reinoud TAILQ_INSERT_TAIL(&fs_nodes, sys_stream_node, next); 3889 1.1 reinoud entry = udf_calc_node_hash(&sys_stream_node->loc); 3890 1.1 reinoud LIST_INSERT_HEAD(&fs_nodes_hash[entry], sys_stream_node, next_hash); 3891 1.1 reinoud } 3892 1.1 reinoud 3893 1.1 reinoud /* pass 1 */ 3894 1.1 reinoud if (!preen) 3895 1.1 reinoud printf("\tPass 1, reading in directory trees\n"); 3896 1.1 reinoud 3897 1.1 reinoud context.unique_id = MAX(0x10, context.unique_id); 3898 1.1 reinoud TAILQ_FOREACH(cur_node, &fs_nodes, next) { 3899 1.1 reinoud /* read in node */ 3900 1.1 reinoud error = udf_read_node_dscr(cur_node, &dscr); 3901 1.1 reinoud if (!error) 3902 1.1 reinoud error = udf_extract_node_info(cur_node, dscr, 0); 3903 1.1 reinoud if (error) { 3904 1.1 reinoud pwarn("%s : invalid reference or bad descriptor, DELETING\n", 3905 1.1 reinoud udf_node_path(cur_node)); 3906 1.1 reinoud udf_recursive_keep(cur_node); 3907 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_NOTFOUND; 3908 1.1 reinoud if (cur_node->parent) { 3909 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR) 3910 1.1 reinoud cur_node->parent->fsck_flags |= 3911 1.1 reinoud FSCK_NODE_FLAG_WIPE_STREAM_DIR; 3912 1.1 reinoud else 3913 1.1 reinoud cur_node->parent->fsck_flags |= 3914 1.1 reinoud FSCK_NODE_FLAG_REPAIRDIR; 3915 1.1 reinoud ; 3916 1.1 reinoud } 3917 1.1 reinoud free(dscr); 3918 1.1 reinoud continue; 3919 1.1 reinoud } 3920 1.1 reinoud 3921 1.1 reinoud if (print_info) { 3922 1.1 reinoud pwarn("Processing %s\n", udf_node_path(cur_node)); 3923 1.1 reinoud print_info = 0; 3924 1.1 reinoud } 3925 1.1 reinoud 3926 1.1 reinoud /* directory found in stream directory? */ 3927 1.1 reinoud if (cur_node->parent && 3928 1.1 reinoud (cur_node->parent->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR) && 3929 1.1 reinoud (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY)) 3930 1.1 reinoud { 3931 1.1 reinoud pwarn("%s : specification violation, directory in stream directory\n", 3932 1.1 reinoud udf_node_path(cur_node)); 3933 1.1 reinoud if (ask(0, "Clear directory")) { 3934 1.1 reinoud udf_recursive_keep(cur_node); 3935 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_NOTFOUND; 3936 1.1 reinoud cur_node->parent->fsck_flags |= 3937 1.1 reinoud FSCK_NODE_FLAG_REPAIRDIR; 3938 1.1 reinoud continue; 3939 1.1 reinoud } 3940 1.1 reinoud } 3941 1.1 reinoud error = udf_process_node_pass1(cur_node, dscr); 3942 1.1 reinoud free(dscr); 3943 1.1 reinoud 3944 1.1 reinoud if (error) 3945 1.1 reinoud return error; 3946 1.1 reinoud } 3947 1.1 reinoud 3948 1.1 reinoud /* pass 1b, if there is overlap, find matching pairs */ 3949 1.1 reinoud dont_repair = false; 3950 1.1 reinoud if (!TAILQ_EMPTY(&fsck_overlaps)) { 3951 1.1 reinoud struct udf_fsck_overlap *overlap; 3952 1.1 reinoud 3953 1.1 reinoud dont_repair = true; 3954 1.1 reinoud pwarn("*** Overlaps detected! rescanning tree for matching pairs ***\n"); 3955 1.1 reinoud TAILQ_FOREACH(cur_node, &fs_nodes, next) { 3956 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND) 3957 1.1 reinoud continue; 3958 1.1 reinoud 3959 1.1 reinoud error = udf_read_node_dscr(cur_node, &dscr); 3960 1.1 reinoud /* should not fail differently */ 3961 1.1 reinoud 3962 1.1 reinoud if (print_info) { 3963 1.1 reinoud pwarn("Processing %s\n", udf_node_path(cur_node)); 3964 1.1 reinoud print_info = 0; 3965 1.1 reinoud } 3966 1.1 reinoud 3967 1.1 reinoud error = udf_process_file( 3968 1.1 reinoud dscr, 3969 1.1 reinoud udf_rw16(cur_node->loc.loc.part_num), 3970 1.1 reinoud NULL, 3971 1.1 reinoud AD_FIND_OVERLAP_PAIR, 3972 1.1 reinoud (void *) cur_node); 3973 1.1 reinoud /* shouldn't fail */ 3974 1.1 reinoud 3975 1.1 reinoud free(dscr); 3976 1.1 reinoud } 3977 1.1 reinoud TAILQ_FOREACH(overlap, &fsck_overlaps, next) { 3978 1.1 reinoud pwarn("%s :overlaps with %s\n", 3979 1.1 reinoud udf_node_path(overlap->node), 3980 1.1 reinoud udf_node_path(overlap->node2)); 3981 1.1 reinoud } 3982 1.1 reinoud if (!preen) 3983 1.1 reinoud printf("\n"); 3984 1.1 reinoud pwarn("*** The following files/directories need to be copied/evacuated:\n"); 3985 1.1 reinoud TAILQ_FOREACH(cur_node, &fs_nodes, next) { 3986 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_OVERLAP) { 3987 1.1 reinoud pwarn("%s : found OVERLAP, evacuate\n", 3988 1.1 reinoud udf_node_path(cur_node)); 3989 1.1 reinoud } 3990 1.1 reinoud } 3991 1.1 reinoud } 3992 1.1 reinoud if (dont_repair) { 3993 1.1 reinoud if (!preen) 3994 1.1 reinoud printf("\n"); 3995 1.1 reinoud pwarn("*** Skipping further repair, only updating free space map if needed\n"); 3996 1.1 reinoud pwarn("*** After deep copying and/or evacuation of these files/directories,\n"); 3997 1.1 reinoud pwarn("*** remove files/directories and re-run fsck_udf\n"); 3998 1.1 reinoud error = udf_prepare_writing(); 3999 1.1 reinoud if (error) 4000 1.1 reinoud return error; 4001 1.1 reinoud 4002 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_OPEN); 4003 1.1 reinoud return 0; 4004 1.1 reinoud } 4005 1.1 reinoud 4006 1.1 reinoud /* pass 2a, checking link counts, object sizes and count files/dirs */ 4007 1.1 reinoud if (!preen) 4008 1.1 reinoud printf("\n\tPass 2, checking link counts, object sizes, stats and cleaning up\n"); 4009 1.1 reinoud 4010 1.1 reinoud TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) { 4011 1.1 reinoud /* not sane to process files/directories that are not found */ 4012 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND) 4013 1.1 reinoud continue; 4014 1.1 reinoud 4015 1.1 reinoud /* shadow VAT */ 4016 1.1 reinoud udf_shadow_VAT_in_use(&cur_node->loc); 4017 1.1 reinoud 4018 1.1 reinoud /* link counts */ 4019 1.1 reinoud if (cur_node->found_link_count != cur_node->link_count) { 4020 1.1 reinoud pwarn("%s : link count incorrect; " 4021 1.1 reinoud "%u instead of declared %u : FIXED\n", 4022 1.1 reinoud udf_node_path(cur_node), 4023 1.1 reinoud cur_node->found_link_count, cur_node->link_count); 4024 1.1 reinoud cur_node->link_count = cur_node->found_link_count; 4025 1.1 reinoud udf_recursive_keep(cur_node); 4026 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY; 4027 1.1 reinoud } 4028 1.1 reinoud 4029 1.1 reinoud /* object sizes */ 4030 1.1 reinoud if (cur_node->declared.obj_size != cur_node->found.obj_size) { 4031 1.1 reinoud pwarn("%s : recorded object size incorrect; " 4032 1.3 martin "%" PRIu64 " instead of declared %" PRIu64 "\n", 4033 1.1 reinoud udf_node_path(cur_node), 4034 1.1 reinoud cur_node->found.obj_size, cur_node->declared.obj_size); 4035 1.1 reinoud cur_node->declared.obj_size = cur_node->found.obj_size; 4036 1.1 reinoud udf_recursive_keep(cur_node); 4037 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY; 4038 1.1 reinoud } 4039 1.1 reinoud 4040 1.1 reinoud /* XXX TODO XXX times */ 4041 1.1 reinoud /* XXX TODO XXX extended attributes location for UDF < 1.50 */ 4042 1.1 reinoud 4043 1.1 reinoud /* validity of UniqueID check */ 4044 1.1 reinoud if (cur_node->parent) { 4045 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_NEW_UNIQUE_ID) { 4046 1.1 reinoud pwarn("%s : assigning new UniqueID\n", 4047 1.1 reinoud udf_node_path(cur_node)); 4048 1.1 reinoud cur_node->unique_id = udf_rw64(context.unique_id); 4049 1.1 reinoud udf_advance_uniqueid(); 4050 1.1 reinoud udf_recursive_keep(cur_node); 4051 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY; 4052 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY) 4053 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR; 4054 1.1 reinoud cur_node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR; 4055 1.1 reinoud } 4056 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_COPY_PARENT_ID) { 4057 1.1 reinoud /* work already done but make note to operator */ 4058 1.1 reinoud pwarn("%s : fixing stream UniqueID to match parent\n", 4059 1.1 reinoud udf_node_path(cur_node)); 4060 1.1 reinoud } 4061 1.1 reinoud } else { 4062 1.1 reinoud if (cur_node->unique_id != 0) { 4063 1.1 reinoud pwarn("%s : bad UniqueID, zeroing\n", 4064 1.1 reinoud udf_node_path(cur_node)); 4065 1.1 reinoud cur_node->unique_id = 0; 4066 1.1 reinoud cur_node->fsck_flags |= 4067 1.1 reinoud FSCK_NODE_FLAG_DIRTY | FSCK_NODE_FLAG_REPAIRDIR; 4068 1.1 reinoud } 4069 1.1 reinoud } 4070 1.1 reinoud 4071 1.1 reinoud /* keep nodes in a repairing dir */ 4072 1.1 reinoud if (cur_node->parent) 4073 1.1 reinoud if (cur_node->parent->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR) 4074 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_KEEP; 4075 1.1 reinoud 4076 1.1 reinoud /* stream directories and files in it are not included */ 4077 1.1 reinoud if (!(cur_node->fsck_flags & FSCK_NODE_FLAG_STREAM)) { 4078 1.1 reinoud /* files / directories counting */ 4079 1.1 reinoud int link_count = cur_node->found_link_count; 4080 1.1 reinoud 4081 1.1 reinoud /* stream directories don't count as link ECMA 4/14.9.6 */ 4082 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_HAS_STREAM_DIR) 4083 1.1 reinoud link_count--; 4084 1.1 reinoud 4085 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY) 4086 1.1 reinoud context.num_directories++; 4087 1.6 riastrad else 4088 1.1 reinoud context.num_files += link_count; 4089 1.1 reinoud ; 4090 1.1 reinoud } 4091 1.1 reinoud } 4092 1.1 reinoud 4093 1.1 reinoud /* pass 2b, cleaning */ 4094 1.1 reinoud open_integrity = 0; 4095 1.1 reinoud TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) { 4096 1.1 reinoud /* can we remove the node? (to save memory) */ 4097 1.1 reinoud if (FSCK_NODE_FLAG_OK(cur_node->fsck_flags)) { 4098 1.1 reinoud TAILQ_REMOVE(&fs_nodes, cur_node, next); 4099 1.1 reinoud LIST_REMOVE(cur_node, next_hash); 4100 1.1 reinoud free(cur_node->directory); 4101 1.1 reinoud bzero(cur_node, sizeof(struct udf_fsck_node)); 4102 1.1 reinoud free(cur_node); 4103 1.1 reinoud } else { 4104 1.1 reinoud /* else keep erroring node */ 4105 1.1 reinoud open_integrity = 1; 4106 1.1 reinoud } 4107 1.1 reinoud } 4108 1.1 reinoud 4109 1.1 reinoud if (!preen) 4110 1.1 reinoud printf("\n\tPreparing disc for writing\n"); 4111 1.1 reinoud error = udf_prepare_writing(); 4112 1.1 reinoud if (error) 4113 1.1 reinoud return error; 4114 1.1 reinoud 4115 1.1 reinoud if (open_integrity) 4116 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_OPEN); 4117 1.1 reinoud 4118 1.1 reinoud /* pass 3 */ 4119 1.1 reinoud if (!preen) 4120 1.1 reinoud printf("\n\tPass 3, fix errors\n"); 4121 1.1 reinoud 4122 1.1 reinoud TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) { 4123 1.1 reinoud /* not sane to process files/directories that are not found */ 4124 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND) 4125 1.1 reinoud continue; 4126 1.1 reinoud 4127 1.1 reinoud /* only interested in bad nodes */ 4128 1.1 reinoud if (FSCK_NODE_FLAG_OK(cur_node->fsck_flags)) 4129 1.1 reinoud continue; 4130 1.1 reinoud 4131 1.1 reinoud error = udf_read_node_dscr(cur_node, &dscr); 4132 1.1 reinoud /* should not fail differently */ 4133 1.1 reinoud 4134 1.1 reinoud /* repair directories */ 4135 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR) 4136 1.1 reinoud udf_node_pass3_repairdir(cur_node, dscr); 4137 1.1 reinoud 4138 1.1 reinoud /* remove invalid stream directories */ 4139 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_WIPE_STREAM_DIR) { 4140 1.1 reinoud assert(udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY); 4141 1.1 reinoud bzero(&dscr->efe.streamdir_icb, sizeof(struct long_ad)); 4142 1.1 reinoud cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY; 4143 1.1 reinoud } 4144 1.1 reinoud 4145 1.1 reinoud if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRTY) 4146 1.1 reinoud udf_node_pass3_writeout_update(cur_node, dscr); 4147 1.1 reinoud free(dscr); 4148 1.1 reinoud } 4149 1.1 reinoud udf_check_shadow_VAT(); 4150 1.1 reinoud 4151 1.1 reinoud return 0; 4152 1.1 reinoud } 4153 1.1 reinoud 4154 1.1 reinoud 4155 1.1 reinoud static void 4156 1.1 reinoud udf_cleanup_after_check(void) 4157 1.1 reinoud { 4158 1.1 reinoud struct udf_fsck_node *cur_node, *next_node; 4159 1.1 reinoud 4160 1.1 reinoud /* XXX yes, there are some small memory leaks here */ 4161 1.1 reinoud 4162 1.1 reinoud /* clean old node info from previous checks */ 4163 1.1 reinoud TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) { 4164 1.1 reinoud TAILQ_REMOVE(&fs_nodes, cur_node, next); 4165 1.1 reinoud LIST_REMOVE(cur_node, next_hash); 4166 1.1 reinoud free(cur_node->directory); 4167 1.1 reinoud free(cur_node); 4168 1.1 reinoud } 4169 1.1 reinoud 4170 1.1 reinoud /* free partition related info */ 4171 1.1 reinoud for (int i = 0; i < UDF_PARTITIONS; i++) { 4172 1.1 reinoud free(context.partitions[i]); 4173 1.1 reinoud free(context.part_unalloc_bits[i]); 4174 1.1 reinoud free(context.part_freed_bits[i]); 4175 1.1 reinoud } 4176 1.1 reinoud 4177 1.1 reinoud /* only free potentional big blobs */ 4178 1.1 reinoud free(context.vat_contents); 4179 1.1 reinoud free(context.lvint_history); 4180 1.1 reinoud 4181 1.1 reinoud free(shadow_vat_contents); 4182 1.1 reinoud shadow_vat_contents = NULL; 4183 1.1 reinoud } 4184 1.1 reinoud 4185 1.1 reinoud 4186 1.1 reinoud static int 4187 1.1 reinoud checkfilesys(char *given_dev) 4188 1.1 reinoud { 4189 1.1 reinoud struct mmc_trackinfo ti; 4190 1.1 reinoud int open_flags; 4191 1.1 reinoud int error; 4192 1.1 reinoud 4193 1.1 reinoud udf_init_create_context(); 4194 1.1 reinoud context.app_name = "*NetBSD UDF"; 4195 1.1 reinoud context.app_version_main = APP_VERSION_MAIN; 4196 1.1 reinoud context.app_version_sub = APP_VERSION_SUB; 4197 1.1 reinoud context.impl_name = IMPL_NAME; 4198 1.1 reinoud 4199 1.1 reinoud emul_mmc_profile = -1; /* invalid->no emulation */ 4200 1.1 reinoud emul_packetsize = 1; /* reasonable default */ 4201 1.1 reinoud emul_sectorsize = 512; /* minimum allowed sector size */ 4202 1.1 reinoud emul_size = 0; /* empty */ 4203 1.1 reinoud 4204 1.1 reinoud if (!preen) 4205 1.1 reinoud pwarn("** Checking UDF file system on %s\n", given_dev); 4206 1.1 reinoud 4207 1.1 reinoud /* reset sticky flags */ 4208 1.1 reinoud rdonly = rdonly_flag; 4209 1.1 reinoud undo_opening_session = 0; /* trying to undo opening of last crippled session */ 4210 1.1 reinoud vat_writeout = 0; /* to write out the VAT anyway */ 4211 1.1 reinoud 4212 1.1 reinoud /* open disc device or emulated file */ 4213 1.1 reinoud open_flags = rdonly ? O_RDONLY : O_RDWR; 4214 1.1 reinoud if (udf_opendisc(given_dev, open_flags)) { 4215 1.1 reinoud udf_closedisc(); 4216 1.1 reinoud warnx("can't open %s", given_dev); 4217 1.1 reinoud return FSCK_EXIT_CHECK_FAILED; 4218 1.1 reinoud } 4219 1.1 reinoud 4220 1.1 reinoud if (!preen) 4221 1.1 reinoud pwarn("** Phase 1 - discovering format from disc\n\n"); 4222 1.1 reinoud 4223 1.1 reinoud /* check if it is an empty disc or no disc in present */ 4224 1.1 reinoud ti.tracknr = mmc_discinfo.first_track; 4225 1.1 reinoud error = udf_update_trackinfo(&ti); 4226 1.1 reinoud if (error || (ti.flags & MMC_TRACKINFO_BLANK)) { 4227 1.1 reinoud /* no use erroring out */ 4228 1.1 reinoud pwarn("Empty disc\n"); 4229 1.1 reinoud return FSCK_EXIT_OK; 4230 1.1 reinoud } 4231 1.1 reinoud 4232 1.1 reinoud context.format_flags = 0; 4233 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) 4234 1.1 reinoud context.format_flags |= FORMAT_SEQUENTIAL; 4235 1.1 reinoud 4236 1.1 reinoud if ((context.format_flags & FORMAT_SEQUENTIAL) && 4237 1.1 reinoud ((mmc_discinfo.disc_state == MMC_STATE_CLOSED) || 4238 1.1 reinoud (mmc_discinfo.disc_state == MMC_STATE_FULL))) { 4239 1.1 reinoud pwarn("Disc is closed or full, can't modify disc\n"); 4240 1.1 reinoud rdonly = 1; 4241 1.1 reinoud } 4242 1.1 reinoud 4243 1.1 reinoud if (target_session) { 4244 1.1 reinoud context.create_new_session = 1; 4245 1.1 reinoud if (target_session < 0) 4246 1.1 reinoud target_session += mmc_discinfo.num_sessions; 4247 1.1 reinoud } else { 4248 1.1 reinoud target_session = mmc_discinfo.num_sessions; 4249 1.1 reinoud if (mmc_discinfo.last_session_state == MMC_STATE_EMPTY) 4250 1.1 reinoud target_session--; 4251 1.1 reinoud } 4252 1.1 reinoud 4253 1.1 reinoud error = udf_get_anchors(); 4254 1.1 reinoud if (error) { 4255 1.1 reinoud udf_closedisc(); 4256 1.1 reinoud pwarn("Failed to retrieve anchors; can't check file system\n"); 4257 1.1 reinoud return FSCK_EXIT_CHECK_FAILED; 4258 1.1 reinoud } 4259 1.1 reinoud 4260 1.1 reinoud udf_check_vrs9660(); 4261 1.1 reinoud 4262 1.1 reinoud /* get both VRS areas */ 4263 1.1 reinoud error = udf_check_VDS_areas(); 4264 1.1 reinoud if (error) { 4265 1.1 reinoud udf_closedisc(); 4266 1.1 reinoud pwarn("Failure reading volume descriptors, disc might be toast\n"); 4267 1.1 reinoud return FSCK_EXIT_CHECK_FAILED; 4268 1.1 reinoud } 4269 1.1 reinoud 4270 1.1 reinoud if (udf_rw32(context.logvol_integrity->integrity_type) == 4271 1.1 reinoud UDF_INTEGRITY_CLOSED) { 4272 1.1 reinoud if (!force) { 4273 1.1 reinoud pwarn("** File system is clean; not checking\n"); 4274 1.1 reinoud return FSCK_EXIT_OK; 4275 1.1 reinoud } 4276 1.1 reinoud pwarn("** File system is already clean\n"); 4277 1.1 reinoud if (!preen) 4278 1.1 reinoud pwarn("\n"); 4279 1.1 reinoud } else { 4280 1.1 reinoud pwarn("** File system not closed properly\n"); 4281 1.1 reinoud if (!preen) 4282 1.1 reinoud printf("\n"); 4283 1.1 reinoud } 4284 1.1 reinoud 4285 1.1 reinoud /* 4286 1.1 reinoud * Only now read in free/unallocated space bitmap. If it reads in fine 4287 1.1 reinoud * it doesn't mean its contents is valid though. Sets partition 4288 1.1 reinoud * lengths too. 4289 1.1 reinoud */ 4290 1.1 reinoud error = udf_readin_partitions_free_space(); 4291 1.1 reinoud if (error) { 4292 1.1 reinoud pwarn("Error during free space bitmap reading\n"); 4293 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_OPEN); 4294 1.1 reinoud } 4295 1.1 reinoud 4296 1.1 reinoud if (!preen) 4297 1.1 reinoud pwarn("** Phase 2 - walking directory tree\n"); 4298 1.1 reinoud 4299 1.1 reinoud udf_suspend_writing(); 4300 1.1 reinoud error = udf_check_directory_tree(); 4301 1.1 reinoud if (error) { 4302 1.1 reinoud if ((!rdonly) && ask(0, "Write out modifications made until now")) 4303 1.1 reinoud udf_allow_writing(); 4304 1.1 reinoud else 4305 1.1 reinoud pwarn("** Aborting repair, not modifying disc\n"); 4306 1.1 reinoud udf_closedisc(); 4307 1.1 reinoud return FSCK_EXIT_CHECK_FAILED; 4308 1.1 reinoud } 4309 1.1 reinoud 4310 1.1 reinoud if (!preen) 4311 1.1 reinoud pwarn("\n** Phase 3 - closing volume if needed\n\n"); 4312 1.1 reinoud 4313 1.1 reinoud /* XXX FAULT INJECTION POINT XXX */ 4314 1.1 reinoud //udf_update_lvintd(UDF_INTEGRITY_OPEN); 4315 1.1 reinoud 4316 1.1 reinoud if (error && rdonly) { 4317 1.1 reinoud pwarn("** Aborting repair, nothing written, disc marked read-only\n"); 4318 1.1 reinoud } else { 4319 1.1 reinoud error = udf_close_volume(); 4320 1.1 reinoud } 4321 1.1 reinoud 4322 1.1 reinoud udf_closedisc(); 4323 1.1 reinoud 4324 1.1 reinoud if (error) 4325 1.1 reinoud return FSCK_EXIT_CHECK_FAILED; 4326 1.1 reinoud return FSCK_EXIT_OK; 4327 1.1 reinoud } 4328 1.1 reinoud 4329 1.1 reinoud 4330 1.1 reinoud static void 4331 1.1 reinoud usage(void) 4332 1.1 reinoud { 4333 1.2 wiz (void)fprintf(stderr, "Usage: %s [-fHnpSsy] file-system ... \n", 4334 1.1 reinoud getprogname()); 4335 1.1 reinoud exit(FSCK_EXIT_USAGE); 4336 1.1 reinoud } 4337 1.1 reinoud 4338 1.1 reinoud 4339 1.1 reinoud static void 4340 1.1 reinoud got_siginfo(int signo) 4341 1.1 reinoud { 4342 1.1 reinoud print_info = 1; 4343 1.1 reinoud } 4344 1.1 reinoud 4345 1.1 reinoud 4346 1.1 reinoud int 4347 1.1 reinoud main(int argc, char **argv) 4348 1.1 reinoud { 4349 1.1 reinoud int ret = FSCK_EXIT_OK, erg; 4350 1.1 reinoud int ch; 4351 1.1 reinoud 4352 1.1 reinoud while ((ch = getopt(argc, argv, "ps:SynfH")) != -1) { 4353 1.1 reinoud switch (ch) { 4354 1.1 reinoud case 'H': 4355 1.1 reinoud heuristics = 1; 4356 1.1 reinoud break; 4357 1.1 reinoud case 'f': 4358 1.1 reinoud force = 1; 4359 1.1 reinoud break; 4360 1.1 reinoud case 'n': 4361 1.1 reinoud rdonly_flag = alwaysno = 1; 4362 1.1 reinoud alwaysyes = preen = 0; 4363 1.1 reinoud break; 4364 1.1 reinoud case 'y': 4365 1.1 reinoud alwaysyes = 1; 4366 1.1 reinoud alwaysno = preen = 0; 4367 1.1 reinoud break; 4368 1.1 reinoud case 'p': 4369 1.1 reinoud /* small automatic repairs */ 4370 1.1 reinoud preen = 1; 4371 1.1 reinoud alwaysyes = alwaysno = 0; 4372 1.1 reinoud break; 4373 1.1 reinoud case 's': 4374 1.1 reinoud /* session number or relative session */ 4375 1.1 reinoud target_session = atoi(optarg); 4376 1.1 reinoud break; 4377 1.1 reinoud case 'S': /* Search for older VATs */ 4378 1.1 reinoud search_older_vat = 1; 4379 1.1 reinoud break; 4380 1.1 reinoud 4381 1.1 reinoud default: 4382 1.1 reinoud usage(); 4383 1.1 reinoud break; 4384 1.1 reinoud } 4385 1.1 reinoud } 4386 1.1 reinoud argc -= optind; 4387 1.1 reinoud argv += optind; 4388 1.1 reinoud 4389 1.1 reinoud if (!argc) 4390 1.1 reinoud usage(); 4391 1.1 reinoud 4392 1.1 reinoud /* TODO SIGINT and SIGQUIT catchers */ 4393 1.1 reinoud #if 0 4394 1.1 reinoud if (signal(SIGINT, SIG_IGN) != SIG_IGN) 4395 1.1 reinoud (void) signal(SIGINT, catch); 4396 1.1 reinoud if (preen) 4397 1.1 reinoud (void) signal(SIGQUIT, catch); 4398 1.1 reinoud #endif 4399 1.1 reinoud 4400 1.1 reinoud signal(SIGINFO, got_siginfo); 4401 1.1 reinoud 4402 1.1 reinoud while (--argc >= 0) { 4403 1.1 reinoud setcdevname(*argv, preen); 4404 1.1 reinoud erg = checkfilesys(*argv++); 4405 1.1 reinoud if (erg > ret) 4406 1.1 reinoud ret = erg; 4407 1.1 reinoud if (!preen) 4408 1.1 reinoud printf("\n"); 4409 1.1 reinoud udf_cleanup_after_check(); 4410 1.1 reinoud } 4411 1.1 reinoud 4412 1.1 reinoud return ret; 4413 1.1 reinoud } 4414 1.1 reinoud 4415 1.1 reinoud 4416 1.1 reinoud /*VARARGS*/ 4417 1.4 riastrad static int __printflike(2, 3) 4418 1.1 reinoud ask(int def, const char *fmt, ...) 4419 1.1 reinoud { 4420 1.1 reinoud va_list ap; 4421 1.1 reinoud 4422 1.1 reinoud char prompt[256]; 4423 1.1 reinoud int c; 4424 1.1 reinoud 4425 1.1 reinoud va_start(ap, fmt); 4426 1.1 reinoud vsnprintf(prompt, sizeof(prompt), fmt, ap); 4427 1.1 reinoud va_end(ap); 4428 1.1 reinoud if (alwaysyes || rdonly) { 4429 1.1 reinoud pwarn("%s? %s\n", prompt, rdonly ? "no" : "yes"); 4430 1.1 reinoud return !rdonly; 4431 1.1 reinoud } 4432 1.1 reinoud if (preen) { 4433 1.1 reinoud pwarn("%s? %s : (default)\n", prompt, def ? "yes" : "no"); 4434 1.1 reinoud return def; 4435 1.1 reinoud } 4436 1.1 reinoud 4437 1.1 reinoud do { 4438 1.1 reinoud pwarn("%s? [yn] ", prompt); 4439 1.1 reinoud fflush(stdout); 4440 1.1 reinoud c = getchar(); 4441 1.1 reinoud while (c != '\n' && getchar() != '\n') 4442 1.1 reinoud if (feof(stdin)) 4443 1.1 reinoud return 0; 4444 1.1 reinoud } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 4445 1.1 reinoud return c == 'y' || c == 'Y'; 4446 1.1 reinoud } 4447 1.1 reinoud 4448 1.1 reinoud 4449 1.1 reinoud /*VARARGS*/ 4450 1.4 riastrad static int __printflike(2, 3) 4451 1.1 reinoud ask_noauto(int def, const char *fmt, ...) 4452 1.1 reinoud { 4453 1.1 reinoud va_list ap; 4454 1.1 reinoud 4455 1.1 reinoud char prompt[256]; 4456 1.1 reinoud int c; 4457 1.1 reinoud 4458 1.1 reinoud va_start(ap, fmt); 4459 1.1 reinoud vsnprintf(prompt, sizeof(prompt), fmt, ap); 4460 1.1 reinoud va_end(ap); 4461 1.1 reinoud #if 0 4462 1.1 reinoud if (preen) { 4463 1.1 reinoud pwarn("%s? %s : (default)\n", prompt, def ? "yes" : "no"); 4464 1.1 reinoud return def; 4465 1.1 reinoud } 4466 1.1 reinoud #endif 4467 1.1 reinoud 4468 1.1 reinoud do { 4469 1.1 reinoud pwarn("%s? [yn] ", prompt); 4470 1.1 reinoud fflush(stdout); 4471 1.1 reinoud c = getchar(); 4472 1.1 reinoud while (c != '\n' && getchar() != '\n') 4473 1.1 reinoud if (feof(stdin)) 4474 1.1 reinoud return 0; 4475 1.1 reinoud } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 4476 1.1 reinoud return c == 'y' || c == 'Y'; 4477 1.1 reinoud } 4478