udftools

- Main Page
- Classes
- Files

- File List
- File Members

All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
udffsck.c
Go to the documentation of this file.
1 /*
2 * udffsck.c
3 *
4 * Copyright (c) 2016 Vojtech Vladyka <vojtch.vladyka@gmail.com>
5 * All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22
23 #include "config.h"
24
25 #include <math.h>
26 #include <time.h>
27 #include <limits.h>
28
29 #include "udffsck.h"
30 #include "utils.h"
31 #include "libudffs.h"
32 #include "options.h"
33
34 // Local function protypes
35 uint8_t get_file(const uint8_t *dev, const struct udf_disc *disc, uint32_t lbnlsn, uint32_t lsn, struct filesystemStats *stats, uint32_t depth, uint32_t uuid, struct fileInfo info, vds_sequence_t *seq );
36 void increment_used_space(struct filesystemStats *stats, uint64_t increment, uint32_t position);
37 uint8_t inspect_fid(const uint8_t *dev, const struct udf_disc *disc, uint32_t lbnlsn, uint32_t lsn, uint8_t *base, uint32_t *pos, struct filesystemStats *stats, uint32_t depth, vds_sequence_t *seq, uint8_t *status);
38 void print_file_chunks(struct filesystemStats *stats);
39 int copy_descriptor(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, uint32_t sourcePosition, uint32_t destinationPosition, size_t size);
40
41 // Local defines
42 #define MARK_BLOCK 1
43 #define UNMARK_BLOCK 0
44
45 #define MAX_DEPTH 100
46
47
55 char * depth2str(uint32_t depth) {
56 static char prefix[MAX_DEPTH] = {0};
57
58 if(depth == 0) {
59 return prefix;
60 }
61
62 if(depth < MAX_DEPTH) {
63 int i=0, c=0;
64 int width = 4;
65 for(i=0, c=0; c<depth-1; c++, i+=width) {
66 strcpy(prefix+i, "\u2502 ");
67 }
68 strcpy(prefix+i, "\u251C\u2500");
69 }
70 return prefix;
71 }
72
82 uint8_t calculate_checksum(tag descTag) {
83 uint8_t i;
84 uint8_t tagChecksum = 0;
85
86 for (i=0; i<16; i++)
87 if (i != 4)
88 tagChecksum += (uint8_t)(((char *)&(descTag))[i]);
89
90 return tagChecksum;
91 }
92
101 int checksum(tag descTag) {
102 uint8_t checksum = calculate_checksum(descTag);
103 dbg("Calc checksum: 0x%02x Tag checksum: 0x%02x\n", checksum, descTag.tagChecksum);
104 return checksum == descTag.tagChecksum;
105 }
106
114 uint16_t calculate_crc(void * restrict desc, uint16_t size) {
115 uint8_t offset = sizeof(tag);
116 tag *descTag = desc;
117 uint16_t crc = 0;
118
119 if(size >= 16) {
120 uint16_t calcCrc = udf_crc((uint8_t *)(desc) + offset, size - offset, crc);
121 return calcCrc;
122 } else {
123 return 0;
124 }
125 }
126
134 int crc(void * restrict desc, uint16_t size) {
135 uint16_t calcCrc = calculate_crc(desc, size);
136 tag *descTag = desc;
137 dbg("Calc CRC: 0x%04x, TagCRC: 0x%04x\n", calcCrc, descTag->descCRC);
138 return le16_to_cpu(descTag->descCRC) != calcCrc;
139 }
140
150 int check_position(tag descTag, uint32_t position) {
151 dbg("tag pos: 0x%x, pos: 0x%x\n", descTag.tagLocation, position);
152 return (descTag.tagLocation != position);
153 }
154
170 char * print_timestamp(timestamp ts) {
171 static char str[34] = {0};
172 uint8_t type = ts.typeAndTimezone >> 12;
173 int16_t offset = (ts.typeAndTimezone & 0x0800) > 0 ? (ts.typeAndTimezone & 0x0FFF) - (0x1000) : (ts.typeAndTimezone & 0x0FFF);
174 int8_t hrso = 0;
175 int8_t mino = 0;
176 dbg("offset: %d\n", offset);
177 if(type == 1 && offset > -2047) { // timestamp is in local time. Convert to UCT.
178 hrso = offset/60; // offset in hours
179 mino = offset%60; // offset in minutes
180 }
181 dbg("TypeAndTimezone: 0x%04x\n", ts.typeAndTimezone);
182 sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d.%02d%02d%02d+%02d:%02d", ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second, ts.centiseconds, ts.hundredsOfMicroseconds, ts.microseconds, hrso, mino);
183 return str;
184 }
185
196 time_t timestamp2epoch(timestamp t) {
197 struct tm tm = {0};
198 tm.tm_year = t.year - 1900;
199 tm.tm_mon = t.month - 1;
200 tm.tm_mday = t.day;
201 tm.tm_hour = t.hour;
202 tm.tm_min = t.minute;
203 tm.tm_sec = t.second;
204 float rest = (t.centiseconds * 10000 + t.hundredsOfMicroseconds * 100 + t.microseconds)/1000000.0;
205 if(rest > 0.5)
206 tm.tm_sec++;
207 uint8_t type = t.typeAndTimezone >> 12;
208 int16_t offset = (t.typeAndTimezone & 0x0800) > 0 ? (t.typeAndTimezone & 0x0FFF) - (0x1000) : (t.typeAndTimezone & 0x0FFF);
209 if(type == 1 && offset > -2047) { // timestamp is in local time. Convert to UCT.
210 int8_t hrso = offset/60; // offset in hours
211 int8_t mino = offset%60; // offset in minutes
212 tm.tm_hour -= hrso;
213 tm.tm_min -= mino;
214 } else if(type == 2) {
215 warn("Time interpretation is not specified.\n");
216 }
217 return mktime(&tm);
218 }
219
229 double compare_timestamps(timestamp a, timestamp b) {
230 double dt = difftime(timestamp2epoch(a), timestamp2epoch(b));
231 return dt;
232 }
233
256 void print_file_info(struct fileInfo info, uint32_t depth) {
257 msg("%s", depth2str(depth));
258
259 //Print file char
260 uint8_t deleted = 0;
261 for(int i=0; i<5; i++) {
262 switch(info.fileCharacteristics & (1 << i)) {
263 case FID_FILE_CHAR_HIDDEN: msg("H"); break;
264 case FID_FILE_CHAR_DIRECTORY:msg("d"); break;
265 case FID_FILE_CHAR_DELETED: msg("D"); deleted = 1; break;
266 case FID_FILE_CHAR_PARENT: msg("P"); break;
267 case FID_FILE_CHAR_METADATA: msg("M"); break;
268 default: msg(".");
269 }
270 }
271
272 if(deleted == 0) {
273 msg(":");
274
275 //Print permissions
276 for(int i=14; i>=0; i--) {
277 switch(info.permissions & (1 << i)) {
278 case FE_PERM_O_EXEC: msg("x"); break;
279 case FE_PERM_O_WRITE: msg("w"); break;
280 case FE_PERM_O_READ: msg("r"); break;
281 case FE_PERM_O_CHATTR: msg("a"); break;
282 case FE_PERM_O_DELETE: msg("d"); break;
283 case FE_PERM_G_EXEC: msg("x"); break;
284 case FE_PERM_G_WRITE: msg("w"); break;
285 case FE_PERM_G_READ: msg("r"); break;
286 case FE_PERM_G_CHATTR: msg("a"); break;
287 case FE_PERM_G_DELETE: msg("d"); break;
288 case FE_PERM_U_EXEC: msg("x"); break;
289 case FE_PERM_U_WRITE: msg("w"); break;
290 case FE_PERM_U_READ: msg("r"); break;
291 case FE_PERM_U_CHATTR: msg("a"); break;
292 case FE_PERM_U_DELETE: msg("d"); break;
293
294 default: msg(".");
295 }
296 if(i == 4 || i == 9 ) {
297 msg(":");
298 }
299 }
300
301 switch(info.fileType) {
302 case ICBTAG_FILE_TYPE_DIRECTORY: msg(" DIR "); break;
303 case ICBTAG_FILE_TYPE_REGULAR: msg(" FILE "); break;
304 case ICBTAG_FILE_TYPE_BLOCK: msg(" BLOCK "); break;
305 case ICBTAG_FILE_TYPE_CHAR: msg(" CHAR "); break;
306 case ICBTAG_FILE_TYPE_FIFO: msg(" FIFO "); break;
307 case ICBTAG_FILE_TYPE_SOCKET: msg(" SOCKET "); break;
308 case ICBTAG_FILE_TYPE_SYMLINK: msg(" SYMLIN "); break;
309 case ICBTAG_FILE_TYPE_STREAMDIR: msg(" STREAM "); break;
310 default: msg(" UNKNOWN "); break;
311 }
312
313 //Print timestamp
314 msg(" %s ", print_timestamp(info.modTime));
315
316 //Print size
317 msg(" %8d ", info.size);
318
319 } else {
320 msg(" <Unused FID> ");
321 }
322
323 //Print filename
324 if(info.filename == NULL) {
325 msg(" <ROOT> ");
326 } else {
327 msg(" \"%s\"", info.filename);
328 }
329
330 msg("\n");
331 }
332
347 int is_udf(uint8_t *dev, int *sectorsize, int force_sectorsize) {
348 struct volStructDesc vsd;
349 struct beginningExtendedAreaDesc bea;
350 struct volStructDesc nsr;
351 struct terminatingExtendedAreaDesc tea;
352 int ssize = 512;
353 int notFound = 0;
354 int foundBEA = 0;
355
356
357 for(int it=0; it<5; it++, ssize *= 2) {
358 if(force_sectorsize) {
359 ssize = *sectorsize;
360 it = INT_MAX - 1; //End after this iteration
361 dbg("Forced sectorsize\n");
362 }
363
364 dbg("Try sectorsize %d\n", ssize);
365
366 for(int i = 0; i<6; i++) {
367 dbg("try #%d at address 0x%x\n", i, 16*BLOCK_SIZE+i*ssize);
368 memcpy(&vsd, dev+16*BLOCK_SIZE+i*ssize, sizeof(vsd));
369 dbg("vsd: type:%d, id:%s, v:%d\n", vsd.structType, vsd.stdIdent, vsd.structVersion);
370
371 if(!strncmp((char *)vsd.stdIdent, VSD_STD_ID_BEA01, 5)) {
372 //It's Extended area descriptor, so it might be UDF, check next sector
373 memcpy(&bea, &vsd, sizeof(bea)); // store it for later
374 foundBEA = 1;
375 } else if(!strncmp((char *)vsd.stdIdent, VSD_STD_ID_BOOT2, 5)) {
376 err("BOOT2 found, unsuported for now.\n");
377 return -1;
378 } else if(!strncmp((char *)vsd.stdIdent, VSD_STD_ID_CD001, 5)) {
379 //CD001 means there is ISO9660, we try search for UDF at sector 18
380 } else if(!strncmp((char *)vsd.stdIdent, VSD_STD_ID_CDW02, 5)) {
381 err("CDW02 found, unsuported for now.\n");
382 return -1;
383 } else if(!strncmp((char *)vsd.stdIdent, VSD_STD_ID_NSR01, 5)) {
384 memcpy(&nsr, &vsd, sizeof(nsr));
385 } else if(!strncmp((char *)vsd.stdIdent, VSD_STD_ID_NSR02, 5)) {
386 memcpy(&nsr, &vsd, sizeof(nsr));
387 } else if(!strncmp((char *)vsd.stdIdent, VSD_STD_ID_NSR03, 5)) {
388 memcpy(&nsr, &vsd, sizeof(nsr));
389 } else if(!strncmp((char *)vsd.stdIdent, VSD_STD_ID_TEA01, 5)) {
390 //We found TEA01, so we can end recognition sequence
391 memcpy(&tea, &vsd, sizeof(tea));
392 break;
393 } else if(vsd.stdIdent[0] == '\0') {
394 if(foundBEA) {
395 continue;
396 }
397 notFound = 1;
398 break;
399 } else {
400 err("Unknown identifier: %s. Exiting\n", vsd.stdIdent);
401 notFound = 1;
402 break;
403 }
404 }
405
406 if(notFound) {
407 notFound = 0;
408 continue;
409 }
410
411 dbg("bea: type:%d, id:%s, v:%d\n", bea.structType, bea.stdIdent, bea.structVersion);
412 dbg("nsr: type:%d, id:%s, v:%d\n", nsr.structType, nsr.stdIdent, nsr.structVersion);
413 dbg("tea: type:%d, id:%s, v:%d\n", tea.structType, tea.stdIdent, tea.structVersion);
414
415 *sectorsize = ssize;
416 return 0;
417 }
418
419 err("Giving up VRS, maybe unclosed or bridged disc.\n");
420 return 1;
421 }
422
431 uint64_t count_used_bits(struct filesystemStats *stats) {
432 if(stats->actPartitionBitmap == NULL)
433 return -1;
434
435 uint64_t countedBits = 0;
436 uint8_t rest = stats->partitionNumOfBits % 8;
437 for(int i = 0; i<stats->partitionNumOfBytes; i++) {
438 uint8_t piece = ~stats->actPartitionBitmap[i];
439 if(i<stats->partitionNumOfBytes-1) {
440 for(int j = 0; j<8; j++) {
441 countedBits += (piece>>j)&1;
442 }
443 } else {
444 for(int j = 0; j<rest; j++) {
445 countedBits += (piece>>j)&1;
446 }
447 }
448 }
449 return countedBits;
450 }
451
469 int get_avdp(uint8_t *dev, struct udf_disc *disc, int *sectorsize, size_t devsize, avdp_type_e type, int force_sectorsize, struct filesystemStats *stats) {
470 int64_t position = 0;
471 tag desc_tag;
472 int ssize = 512;
473 int it = 0;
474 int status = 0;
475
476 for(int it = 0; it < 5; it++, ssize *= 2) {
477
478 //Check if sectorsize is already found
479 if(force_sectorsize) {
480 ssize = *sectorsize;
481 it = INT_MAX-1; //break after this round
482 }
483 dbg("Trying sectorsize %d\n", ssize);
484
485 //Reset status for new round
486 status = 0;
487
488 if(type == 0) {
489 position = ssize*256; //First AVDP is on LSN=256
490 } else if(type == 1) {
491 position = devsize-ssize; //Second AVDP is on last LSN
492 } else if(type == 2) {
493 position = devsize-ssize-256*ssize; //Third AVDP can be at last LSN-256
494 } else {
495 position = ssize*512; //Unclosed disc have AVDP at sector 512
496 type = 0; //Save it to FIRST_AVDP positon
497 }
498
499 dbg("DevSize: %zu\n", devsize);
500 dbg("Current position: %lx\n", position);
501
502 if(disc->udf_anchor[type] == NULL) {
503 disc->udf_anchor[type] = malloc(sizeof(struct anchorVolDescPtr)); // Prepare memory for AVDP
504 }
505
506 desc_tag = *(tag *)(dev+position);
507
508 if(!checksum(desc_tag)) {
509 status |= E_CHECKSUM;
510 continue;
511 }
512 if(le16_to_cpu(desc_tag.tagIdent) != TAG_IDENT_AVDP) {
513 status |= E_WRONGDESC;
514 continue;
515 }
516 dbg("Tag Serial Num: %d\n", desc_tag.tagSerialNum);
517 if(stats->AVDPSerialNum == 0xFFFF) { // Default state -> save first found
518 stats->AVDPSerialNum = desc_tag.tagSerialNum;
519 } else if(stats->AVDPSerialNum != desc_tag.tagSerialNum) { //AVDP serial numbers differs, no recovery support. UDF 2.1.6
520 stats->AVDPSerialNum = 0; //No recovery support
521 }
522
523 memcpy(disc->udf_anchor[type], dev+position, sizeof(struct anchorVolDescPtr));
524
525 if(crc(disc->udf_anchor[type], sizeof(struct anchorVolDescPtr))) {
526 status |= E_CRC;
527 continue;
528 }
529
530 if(check_position(desc_tag, position/ssize)) {
531 status |= E_POSITION;
532 continue;
533 }
534
535 dbg("AVDP[%d]: Main Ext Len: %d, Reserve Ext Len: %d\n", type, disc->udf_anchor[type]->mainVolDescSeqExt.extLength, disc->udf_anchor[type]->reserveVolDescSeqExt.extLength);
536 if(disc->udf_anchor[type]->mainVolDescSeqExt.extLength < 16*ssize || disc->udf_anchor[type]->reserveVolDescSeqExt.extLength < 16*ssize) {
537 status |= E_EXTLEN;
538 }
539
540 msg("AVDP[%d] successfully loaded.\n", type);
541 *sectorsize = ssize;
542
543 if(status & E_CHECKSUM) {
544 err("Checksum failure at AVDP[%d]\n", type);
545 }
546 if(status & E_WRONGDESC) {
547 err("AVDP not found at 0x%lx\n", position);
548 }
549 if(status & E_CRC) {
550 err("CRC error at AVDP[%d]\n", type);
551 }
552 if(status & E_POSITION) {
553 err("Position mismatch at AVDP[%d]\n", type);
554 }
555 if(status & E_EXTLEN) {
556 err("Main or Reserve Extent Length at AVDP[%d] is less than 16 sectors\n", type);
557 }
558 return status;
559 }
560 return status;
561 }
562
563
576 int get_vds(uint8_t *dev, struct udf_disc *disc, int sectorsize, avdp_type_e avdp, vds_type_e vds, vds_sequence_t *seq) {
577 uint8_t *position;
578 int8_t counter = 0;
579 tag descTag;
580
581 // Go to first address of VDS
582 switch(vds) {
583 case MAIN_VDS:
584 position = dev+sectorsize*(disc->udf_anchor[avdp]->mainVolDescSeqExt.extLocation);
585 break;
586 case RESERVE_VDS:
587 position = dev+sectorsize*(disc->udf_anchor[avdp]->reserveVolDescSeqExt.extLocation);
588 break;
589 }
590 dbg("Current position: %lx\n", position-dev);
591
592 // Go thru descriptors until TagIdent is 0 or amout is too big to be real
593 while(counter < VDS_STRUCT_AMOUNT) {
594
595 // Read tag
596 memcpy(&descTag, position, sizeof(descTag));
597
598 dbg("Tag ID: %d\n", descTag.tagIdent);
599
600 if(vds == MAIN_VDS) {
601 seq->main[counter].tagIdent = descTag.tagIdent;
602 seq->main[counter].tagLocation = (position-dev)/sectorsize;
603 } else {
604 seq->reserve[counter].tagIdent = descTag.tagIdent;
605 seq->reserve[counter].tagLocation = (position-dev)/sectorsize;
606 }
607
608 counter++;
609
610 // What kind of descriptor is that?
611 switch(le16_to_cpu(descTag.tagIdent)) {
612 case TAG_IDENT_PVD:
613 if(disc->udf_pvd[vds] != 0) {
614 err("Structure PVD is already set. Probably error at tag or media\n");
615 return -4;
616 }
617 disc->udf_pvd[vds] = malloc(sizeof(struct primaryVolDesc)); // Prepare memory
618 memcpy(disc->udf_pvd[vds], position, sizeof(struct primaryVolDesc));
619 dbg("VolNum: %d\n", disc->udf_pvd[vds]->volDescSeqNum);
620 dbg("pVolNum: %d\n", disc->udf_pvd[vds]->primaryVolDescNum);
621 dbg("seqNum: %d\n", disc->udf_pvd[vds]->volSeqNum);
622 dbg("predLoc: %d\n", disc->udf_pvd[vds]->predecessorVolDescSeqLocation);
623 break;
624 case TAG_IDENT_IUVD:
625 if(disc->udf_iuvd[vds] != 0) {
626 err("Structure IUVD is already set. Probably error at tag or media\n");
627 return -4;
628 }
629 disc->udf_iuvd[vds] = malloc(sizeof(struct impUseVolDesc)); // Prepare memory
630 memcpy(disc->udf_iuvd[vds], position, sizeof(struct impUseVolDesc));
631 break;
632 case TAG_IDENT_PD:
633 if(disc->udf_pd[vds] != 0) {
634 err("Structure PD is already set. Probably error at tag or media\n");
635 return -4;
636 }
637 disc->udf_pd[vds] = malloc(sizeof(struct partitionDesc)); // Prepare memory
638 memcpy(disc->udf_pd[vds], position, sizeof(struct partitionDesc));
639 break;
640 case TAG_IDENT_LVD:
641 if(disc->udf_lvd[vds] != 0) {
642 err("Structure LVD is already set. Probably error at tag or media\n");
643 return -4;
644 }
645 dbg("LVD size: 0x%lx\n", sizeof(struct logicalVolDesc));
646
647 struct logicalVolDesc *lvd;
648 lvd = (struct logicalVolDesc *)(position);
649
650 disc->udf_lvd[vds] = malloc(sizeof(struct logicalVolDesc)+lvd->mapTableLength); // Prepare memory
651 memcpy(disc->udf_lvd[vds], position, sizeof(struct logicalVolDesc)+lvd->mapTableLength);
652 dbg("NumOfPartitionMaps: %d\n", disc->udf_lvd[vds]->numPartitionMaps);
653 dbg("MapTableLength: %d\n", disc->udf_lvd[vds]->mapTableLength);
654 for(int i=0; i<le32_to_cpu(lvd->mapTableLength); i++) {
655 note("[0x%02x] ", disc->udf_lvd[vds]->partitionMaps[i]);
656 }
657 note("\n");
658 break;
659 case TAG_IDENT_USD:
660 if(disc->udf_usd[vds] != 0) {
661 err("Structure USD is already set. Probably error at tag or media\n");
662 return -4;
663 }
664
665 struct unallocSpaceDesc *usd;
666 usd = (struct unallocSpaceDesc *)(position);
667 dbg("VolDescNum: %d\n", usd->volDescSeqNum);
668 dbg("NumAllocDesc: %d\n", usd->numAllocDescs);
669
670 disc->udf_usd[vds] = malloc(sizeof(struct unallocSpaceDesc)+(usd->numAllocDescs)*sizeof(extent_ad)); // Prepare memory
671 memcpy(disc->udf_usd[vds], position, sizeof(struct unallocSpaceDesc)+(usd->numAllocDescs)*sizeof(extent_ad));
672 break;
673 case TAG_IDENT_TD:
674 if(disc->udf_td[vds] != 0) {
675 err("Structure TD is already set. Probably error at tag or media\n");
676 return -4;
677 }
678 disc->udf_td[vds] = malloc(sizeof(struct terminatingDesc)); // Prepare memory
679 memcpy(disc->udf_td[vds], position, sizeof(struct terminatingDesc));
680 // Found terminator, ending.
681 return 0;
682 case 0:
683 // Found end of VDS, ending.
684 return 0;
685 default:
686 // Unkown TAG
687 fatal("Unknown TAG found at %p. Ending.\n", position);
688 return -3;
689 }
690
691 position = position + sectorsize;
692 dbg("New positon is 0x%lx\n", position-dev);
693 }
694 return 0;
695 }
696
709 int get_correct(vds_sequence_t *seq, uint16_t tagIdent) {
710 for(int i=0; i<VDS_STRUCT_AMOUNT; i++) {
711 if(seq->main[i].tagIdent == tagIdent && (seq->main[i].error & (E_CRC | E_CHECKSUM | E_WRONGDESC)) == 0) {
712 return MAIN_VDS;
713 } else if(seq->reserve[i].tagIdent == tagIdent && (seq->reserve[i].error & (E_CRC | E_CHECKSUM | E_WRONGDESC)) == 0) {
714 return RESERVE_VDS;
715 }
716 }
717 return -1;
718 }
719
734 int get_lvid(uint8_t *dev, struct udf_disc *disc, int sectorsize, struct filesystemStats *stats, vds_sequence_t *seq ) {
735 if(disc->udf_lvid != 0) {
736 err("Structure LVID is already set. Probably error at tag or media\n");
737 return 4;
738 }
739 int vds = -1;
740 if((vds=get_correct(seq, TAG_IDENT_LVD)) < 0) {
741 err("No correct LVD found. Aborting.\n");
742 return 4;
743 }
744
745 uint32_t loc = disc->udf_lvd[vds]->integritySeqExt.extLocation;
746 uint32_t len = disc->udf_lvd[vds]->integritySeqExt.extLength;
747 dbg("LVID: loc: %d, len: %d\n", loc, len);
748
749 struct logicalVolIntegrityDesc *lvid;
750 lvid = (struct logicalVolIntegrityDesc *)(dev+loc*sectorsize);
751
752 disc->udf_lvid = malloc(len);
753 memcpy(disc->udf_lvid, dev+loc*sectorsize, len);
754 dbg("LVID: lenOfImpUse: %d\n",disc->udf_lvid->lengthOfImpUse);
755 dbg("LVID: numOfPartitions: %d\n", disc->udf_lvid->numOfPartitions);
756
757 struct impUseLVID *impUse = (struct impUseLVID *)((uint8_t *)(disc->udf_lvid) + sizeof(struct logicalVolIntegrityDesc) + 8*disc->udf_lvid->numOfPartitions); //this is because of ECMA 167r3, 3/24, fig 22
758 uint8_t *impUseArr = (uint8_t *)impUse;
759 stats->actUUID = (((struct logicalVolHeaderDesc *)(disc->udf_lvid->logicalVolContentsUse))->uniqueID);
760
761 stats->LVIDtimestamp = lvid->recordingDateAndTime;
762
763 dbg("LVID: number of files: %d\n", impUse->numOfFiles);
764 dbg("LVID: number of dirs: %d\n", impUse->numOfDirs);
765 dbg("LVID: UDF rev: min read: %04x\n", impUse->minUDFReadRev);
766 dbg(" min write: %04x\n", impUse->minUDFWriteRev);
767 dbg(" max write: %04x\n", impUse->maxUDFWriteRev);
768 dbg("Next Unique ID: %d\n", stats->actUUID);
769 dbg("LVID recording timestamp: %s\n", print_timestamp(stats->LVIDtimestamp));
770
771 stats->expNumOfFiles = impUse->numOfFiles;
772 stats->expNumOfDirs = impUse->numOfDirs;
773
774 stats->minUDFReadRev = impUse->minUDFReadRev;
775 stats->minUDFWriteRev = impUse->minUDFWriteRev;
776 stats->maxUDFWriteRev = impUse->maxUDFWriteRev;
777
778 dbg("Logical Volume Contents Use\n");
779 for(int i=0; i<32; ) {
780 for(int j=0; j<8; j++, i++) {
781 note("%02x ", disc->udf_lvid->logicalVolContentsUse[i]);
782 }
783 note("\n");
784 }
785 dbg("Free Space Table\n");
786 for(int i=0; i<disc->udf_lvid->numOfPartitions * 4; i++) {
787 note("0x%08x, %d\n", disc->udf_lvid->freeSpaceTable[i], disc->udf_lvid->freeSpaceTable[i]);
788 }
789 stats->freeSpaceBlocks = disc->udf_lvid->freeSpaceTable[0];
790 stats->partitionSizeBlocks = disc->udf_lvid->freeSpaceTable[1];
791
792 dbg("Size Table\n");
793 for(int i=disc->udf_lvid->numOfPartitions * 4; i<disc->udf_lvid->numOfPartitions * 4 * 2; i++) {
794 note("0x%08x, %d\n", disc->udf_lvid->freeSpaceTable[i],disc->udf_lvid->freeSpaceTable[i]);
795 }
796
797 if(disc->udf_lvid->nextIntegrityExt.extLength > 0) {
798 dbg("Next integrity extent found.\n");
799 } else {
800 dbg("No other integrity extents are here.\n");
801 }
802
803 return 0;
804 }
805
818 int get_volume_identifier(struct udf_disc *disc, struct filesystemStats *stats, vds_sequence_t *seq ) {
819 int vds = -1;
820 if((vds=get_correct(seq, TAG_IDENT_PVD)) < 0) {
821 err("No correct PVD found. Aborting.\n");
822 return 4;
823 }
824 stats->volumeSetIdent = disc->udf_pvd[vds]->volSetIdent;
825 stats->partitionIdent = disc->udf_fsd->logicalVolIdent;
826 return 0;
827 }
828
843 uint8_t markUsedBlock(struct filesystemStats *stats, uint32_t lbn, uint32_t size, uint8_t mark) {
844 if(lbn+size < stats->partitionNumOfBits) {
845 uint32_t byte = 0;
846 uint8_t bit = 0;
847
848 dbg("Marked LBN %d with size %d\n", lbn, size);
849 if(size == 0) {
850 dbg("Size is 0, return.\n");
851 return 0;
852 }
853 int i = 0;
854 do {
855 byte = lbn/8;
856 bit = lbn%8;
857 if(mark) { // write 0
858 if(stats->actPartitionBitmap[byte] & (1<<bit)) {
859 stats->actPartitionBitmap[byte] &= ~(1<<bit);
860 } else {
861 err("[%d:%d]Error marking block as used. It is already marked.\n", byte, bit);
862 }
863 } else { // write 1
864 if(stats->actPartitionBitmap[byte] & (1<<bit)) {
865 err("[%d:%d]Error marking block as unused. It is already unmarked.\n", byte, bit);
866 } else {
867 stats->actPartitionBitmap[byte] |= 1<<bit;
868 }
869 }
870 lbn++;
871 i++;
872 } while(i < size);
873 dbg("Last LBN: %d, Byte: %d, Bit: %d\n", lbn, byte, bit);
874 dbg("Real size: %d\n", i);
875
876 #if 0 // For debug purposes only
877 note("\n ACT \t EXP\n");
878 uint32_t shift = 0;
879 for(int i=0+shift, k=0+shift; i<stats->partitionSizeBlocks/8 && i < 100+shift; ) {
880 for(int j=0; j<16; j++, i++) {
881 note("%02x ", stats->actPartitionBitmap[i]);
882 }
883 note("| ");
884 for(int j=0; j<16; j++, k++) {
885 note("%02x ", stats->expPartitionBitmap[k]);
886 }
887 note("\n");
888 }
889 note("\n");
890 shift = 4400;
891 for(int i=0+shift, k=0+shift; i<stats->partitionSizeBlocks/8 && i < 100+shift; ) {
892 for(int j=0; j<16; j++, i++) {
893 note("%02x ", stats->actPartitionBitmap[i]);
894 }
895 note("| ");
896 for(int j=0; j<16; j++, k++) {
897 note("%02x ", stats->expPartitionBitmap[k]);
898 }
899 note("\n");
900 }
901 note("\n");
902 #endif
903 } else {
904 err("MARKING USED BLOCK TO BITMAP FAILED\n");
905 return -1;
906 }
907 return 0;
908 }
909
923 uint8_t get_fsd(uint8_t *dev, struct udf_disc *disc, int sectorsize, uint32_t *lbnlsn, struct filesystemStats * stats, vds_sequence_t *seq) {
924 long_ad *lap;
925 tag descTag;
926 int vds = -1;
927
928 if((vds=get_correct(seq, TAG_IDENT_PD)) < 0) {
929 err("No correct PD found. Aborting.\n");
930 return 4;
931 }
932 dbg("PD partNum: %d\n", disc->udf_pd[vds]->partitionNumber);
933 uint32_t lsnBase = 0;
934 lsnBase = disc->udf_pd[vds]->partitionStartingLocation;
935 dbg("Partition Length: %d\n", disc->udf_pd[vds]->partitionLength);
936
937 dbg("LSN base: %d\n", lsnBase);
938
939 vds = -1;
940 if((vds=get_correct(seq, TAG_IDENT_LVD)) < 0) {
941 err("No correct LVD found. Aborting.\n");
942 return 4;
943 }
944 uint32_t lbSize = le32_to_cpu(disc->udf_lvd[vds]->logicalBlockSize);
945
946 lap = (long_ad *)disc->udf_lvd[vds]->logicalVolContentsUse; //FIXME BIG_ENDIAN use lela_to_cpu, but not on ptr to disc. Must store it on different place.
947 lb_addr filesetblock = lelb_to_cpu(lap->extLocation);
948 uint32_t filesetlen = lap->extLength;
949
950 dbg("FSD at (%d, p%d)\n",
951 lap->extLocation.logicalBlockNum,
952 lap->extLocation.partitionReferenceNum);
953
954 dbg("LAP: length: %x, LBN: %x, PRN: %x\n", filesetlen, filesetblock.logicalBlockNum, filesetblock.partitionReferenceNum);
955 dbg("LAP: LSN: %d\n", lsnBase/*+filesetblock.logicalBlockNum*/);
956
957 disc->udf_fsd = malloc(sizeof(struct fileSetDesc));
958 memcpy(disc->udf_fsd, dev+(lsnBase+filesetblock.logicalBlockNum)*lbSize, sizeof(struct fileSetDesc));
959
960 if(le16_to_cpu(disc->udf_fsd->descTag.tagIdent) != TAG_IDENT_FSD) {
961 err("Error identifiing FSD. Tag ID: 0x%x\n", disc->udf_fsd->descTag.tagIdent);
962 free(disc->udf_fsd);
963 return 8;
964 }
965 dbg("LogicVolIdent: %s\nFileSetIdent: %s\n", (disc->udf_fsd->logicalVolIdent), (disc->udf_fsd->fileSetIdent));
966
967 increment_used_space(stats, filesetlen, lap->extLocation.logicalBlockNum);
968
969 *lbnlsn = lsnBase;
970 return 0;
971 }
972
991 uint8_t inspect_aed(const uint8_t *dev, uint32_t lsnBase, uint32_t aedlbn, uint32_t *lengthADArray, uint8_t **ADArray, struct filesystemStats *stats, uint8_t *status) {
992 uint16_t lbSize = stats->blocksize;
993 uint32_t lad = 0;
994 uint32_t nAD = 0;
995 short_ad *sad = NULL;
996
997 struct allocExtDesc *aed = (struct allocExtDesc *)(dev + (lsnBase + aedlbn)*lbSize);
998 if(aed->descTag.tagIdent == TAG_IDENT_AED) {
999 //checksum
1000 if(!checksum(aed->descTag)) {
1001 err("AED checksum failed\n");
1002 *status |= 4;
1003 return 4;
1004 }
1005 //CRC
1006 #if 0
1007 dbg("AED: descCRCLength: %d, LAD: %d\n", aed->descTag.descCRCLength, aed->lengthAllocDescs);
1008 dbg("AED: CRC: 0x%04x\n", aed->descTag.descCRC);
1009 for(int i=16; i<aed->descTag.descCRCLength+16; i++) {
1010 dbg("[%d]: CRC: 0x%04x\n", i, udf_crc((uint8_t *)(aed) + sizeof(tag), i - sizeof(tag), 0));
1011 }
1012 if(crc(aed, aed->descTag.descCRCLength-8)) {
1013 err("AED CRC failed\n");
1014 *status |= 4;
1015 return 4;
1016 }
1017 #endif
1018 // position
1019 if(check_position(aed->descTag, aedlbn)) {
1020 err("AED position differs\n");
1021 *status |= 4;
1022 }
1023
1024 lad = aed->lengthAllocDescs;
1025 *ADArray = (uint8_t *)(aed)+sizeof(struct allocExtDesc);
1026 *lengthADArray = lad;
1027 #if 0 //For debug purposes only
1028 uint32_t line = 0;
1029 dbg("AED Array\n");
1030 for(int i=0; i<*lengthADArray; ) {
1031 note("[%04d] ",line++);
1032 for(int j=0; j<8; j++, i++) {
1033 note("%02x ", (*ADArray)[i]);
1034 }
1035 note("\n");
1036 }
1037 #endif
1038 dbg("ADArray ptr: %p\n", *ADArray);
1039 dbg("lengthADArray: %d\n", *lengthADArray);
1040 increment_used_space(stats, lad%lbSize == 0 ? lad/lbSize : lad/lbSize + 1, aedlbn);
1041 return 0;
1042 } else {
1043 err("There should be AED, but is not\n");
1044 }
1045 return 4;
1046 }
1047
1074 uint8_t translate_fid(const uint8_t *dev, const struct udf_disc *disc, uint32_t lbnlsn, uint32_t lsn, uint8_t *allocDescs, uint32_t lengthAllocDescs, uint16_t icb_ad, struct filesystemStats *stats, uint32_t depth, vds_sequence_t *seq, uint8_t *status) {
1075
1076 uint32_t descSize = 0;
1077 uint8_t *fidArray = NULL;
1078 uint32_t nAD = 0;
1079 uint32_t overallLength = 0;
1080 uint32_t overallBodyLength = 0;
1081 short_ad *sad = NULL;
1082 long_ad *lad = NULL;
1083 ext_ad *ead = NULL;
1084 uint16_t lbSize = stats->blocksize;
1085 uint32_t lsnBase = lbnlsn;
1086
1087 switch(icb_ad) {
1088 case ICBTAG_FLAG_AD_SHORT:
1089 dbg("Short AD\n");
1090 descSize = sizeof(short_ad);
1091 break;
1092 case ICBTAG_FLAG_AD_LONG:
1093 dbg("Long AD\n");
1094 descSize = sizeof(long_ad);
1095 break;
1096 case ICBTAG_FLAG_AD_EXTENDED:
1097 dbg("Extended AD\n");
1098 descSize = sizeof(ext_ad);
1099 break;
1100 defualt:
1101 err("[translate_fid] Unsupported icb_ad: 0x%04x\n", icb_ad);
1102 return 1;
1103 }
1104 dbg("LengthOfAllocDescs: %d\n", lengthAllocDescs);
1105
1106 nAD = lengthAllocDescs/descSize;
1107
1108 #if 0 // For debug purposes only
1109 uint32_t line = 0;
1110 dbg("FID Alloc Array\n");
1111 for(int i=0; i<lengthAllocDescs; ) {
1112 note("[%04d] ",line++);
1113 for(int j=0; j<8; j++, i++) {
1114 note("%02x ", allocDescs[i]);
1115 }
1116 note("\n");
1117 }
1118 #endif
1119
1120 uint32_t lengthADArray = 0;
1121 uint8_t *ADArray = NULL;
1122
1123 for(int i = 0; i < nAD; i++) {
1124 uint32_t aedlbn = 0;
1125 sad = (short_ad *)(allocDescs + i*descSize); //we can do that, beause all ADs have size as first.
1126 overallLength += sad->extLength & 0x3FFFFFFF; //lower 30 bits are unsiged length
1127 overallBodyLength += lbSize;
1128 dbg("ExtLength: %d, type: %d\n", sad->extLength & 0x3FFFFFFF, sad->extLength>>30);
1129 if(sad->extLength>>30 == 3) { //Extent is AED
1130 switch(icb_ad) {
1131 case ICBTAG_FLAG_AD_SHORT:
1132 //we already have sad
1133 aedlbn = sad->extPosition;
1134 break;
1135 case ICBTAG_FLAG_AD_LONG:
1136 lad = (long_ad *)(allocDescs + i*descSize);
1137 aedlbn = lad->extLocation.logicalBlockNum;
1138 break;
1139 case ICBTAG_FLAG_AD_EXTENDED:
1140 ead = (ext_ad *)(allocDescs + i*descSize);
1141 aedlbn = ead->extLocation.logicalBlockNum;
1142 break;
1143 }
1144 if(inspect_aed(dev, lsnBase, aedlbn, &lengthADArray, &ADArray, stats, status)) {
1145 err("AED inspection failed.\n");
1146 return -1;
1147 }
1148 #if 1
1149 uint32_t line = 0;
1150 dbg("FID Alloc Array after AED\n");
1151 dbg("ADArray ptr: %p\n", ADArray);
1152 dbg("lengthADArray: %d\n", lengthADArray);
1153 #endif
1154 #if 0 //For debug purposes only
1155 for(int i=0; i<lengthADArray; ) {
1156 note("[%04d] ",line++);
1157 for(int j=0; j<descSize; j++, i++) {
1158 note("%02x ", ADArray[i]);
1159 }
1160 note("\n");
1161 }
1162 #endif
1163 nAD += lengthADArray/descSize;
1164 overallBodyLength += lengthADArray;
1165 overallLength += lengthADArray;
1166 }
1167 }
1168
1169 dbg("Overall length: %d\n", overallLength);
1170 fidArray = calloc(1, overallBodyLength);
1171 if(fidArray == NULL) {
1172 err("FID array allocatiob failed.\n");
1173 return 2;
1174 }
1175
1176 uint32_t prevExtLength = 0;
1177 uint8_t aed = 0;
1178 for(int i = 0; i < nAD; i++) {
1179 switch(icb_ad) {
1180 case ICBTAG_FLAG_AD_SHORT:
1181 if(aed) {
1182 sad = (short_ad *)(ADArray + i*descSize - lengthAllocDescs);
1183 } else {
1184 sad = (short_ad *)(allocDescs + i*descSize);
1185 }
1186 if(sad->extLength >> 30 == 3) { //Extent is AED
1187 aed = 1;
1188 continue;
1189 }
1190 memcpy(fidArray+prevExtLength, (uint8_t *)(dev + (lsnBase + sad->extPosition)*lbSize), sad->extLength);
1191 increment_used_space(stats, 1, sad->extPosition);
1192 prevExtLength += sad->extLength;
1193 break;
1194 case ICBTAG_FLAG_AD_LONG:
1195 if(aed) {
1196 lad = (long_ad *)(ADArray + i*descSize - lengthAllocDescs);
1197 } else {
1198 lad = (long_ad *)(allocDescs + i*descSize);
1199 }
1200 if(lad->extLength >> 30 == 3) { //Extent is AED
1201 aed = 1;
1202 continue;
1203 }
1204 memcpy(fidArray+prevExtLength, (uint8_t *)(dev + (lsnBase + lad->extLocation.logicalBlockNum)*lbSize), lad->extLength);
1205 increment_used_space(stats, 1, lad->extLocation.logicalBlockNum);
1206 prevExtLength += lad->extLength;
1207 break;
1208 case ICBTAG_FLAG_AD_EXTENDED:
1209 if(aed) {
1210 ead = (ext_ad *)(ADArray + i*descSize - lengthAllocDescs);
1211 } else {
1212 ead = (ext_ad *)(allocDescs + i*descSize);
1213 }
1214 if(ead->extLength >> 30 == 3) { //Extent is AED
1215 aed = 1;
1216 continue;
1217 }
1218 memcpy(fidArray+prevExtLength, (uint8_t *)(dev + (lsnBase + ead->extLocation.logicalBlockNum)*lbSize), ead->extLength);
1219 increment_used_space(stats, 1, ead->extLocation.logicalBlockNum);
1220 prevExtLength += ead->extLength;
1221 break;
1222 }
1223 }
1224
1225 uint8_t tempStatus = 0;
1226 int counter = 0;
1227 for(uint32_t pos=0; pos < overallLength; ) {
1228 dbg("FID #%d\n", counter++);
1229 if(inspect_fid(dev, disc, lbnlsn, lsn, fidArray, &pos, stats, depth+1, seq, &tempStatus) != 0) {
1230 dbg("1 FID inspection over.\n");
1231 break;
1232 }
1233 }
1234 dbg("2 FID inspection over.\n");
1235
1236 aed = 0;
1237 if(tempStatus & 0x01) { //Something was fixed - we need to copy back array
1238 prevExtLength = 0;
1239 for(int i = 0; i < nAD; i++) {
1240 switch(icb_ad) {
1241 case ICBTAG_FLAG_AD_SHORT:
1242 if(aed) {
1243 sad = (short_ad *)(ADArray + i*descSize - lengthAllocDescs);
1244 } else {
1245 sad = (short_ad *)(allocDescs + i*descSize);
1246 }
1247 if(sad->extLength >> 30 == 3) { //Extent is AED
1248 aed = 1;
1249 continue;
1250 }
1251 memcpy((uint8_t *)(dev + (lsnBase + sad->extPosition)*lbSize), fidArray+prevExtLength, sad->extLength);
1252 prevExtLength += sad->extLength;
1253 break;
1254 case ICBTAG_FLAG_AD_LONG:
1255 if(aed) {
1256 lad = (long_ad *)(ADArray + i*descSize - lengthAllocDescs);
1257 } else {
1258 lad = (long_ad *)(allocDescs + i*descSize);
1259 }
1260 if(lad->extLength >> 30 == 3) { //Extent is AED
1261 aed = 1;
1262 continue;
1263 }
1264 memcpy((uint8_t *)(dev + (lsnBase + lad->extLocation.logicalBlockNum)*lbSize), fidArray+prevExtLength, lad->extLength);
1265 prevExtLength += lad->extLength;
1266 break;
1267 case ICBTAG_FLAG_AD_EXTENDED:
1268 if(aed) {
1269 ead = (ext_ad *)(ADArray + i*descSize - lengthAllocDescs);
1270 } else {
1271 ead = (ext_ad *)(allocDescs + i*descSize);
1272 }
1273 if(ead->extLength >> 30 == 3) { //Extent is AED
1274 aed = 1;
1275 continue;
1276 }
1277 memcpy((uint8_t *)(dev + (lsnBase + ead->extLocation.logicalBlockNum)*lbSize), fidArray+prevExtLength, ead->extLength);
1278 prevExtLength += ead->extLength;
1279 break;
1280 }
1281 }
1282 }
1283
1284
1285 //free array
1286 free(fidArray);
1287 (*status) |= tempStatus;
1288 return 0;
1289 }
1290
1315 uint8_t inspect_fid(const uint8_t *dev, const struct udf_disc *disc, uint32_t lbnlsn, uint32_t lsn, uint8_t *base, uint32_t *pos, struct filesystemStats *stats, uint32_t depth, vds_sequence_t *seq, uint8_t *status) {
1316 uint32_t flen, padding;
1317 uint32_t lsnBase = lbnlsn;
1318 struct fileIdentDesc *fid = (struct fileIdentDesc *)(base + *pos);
1319 struct fileInfo info = {0};
1320
1321 dbg("FID pos: 0x%x\n", *pos);
1322 if (!checksum(fid->descTag)) {
1323 err("[inspect fid] FID checksum failed.\n");
1324 return -4;
1325 warn("DISABLED ERROR RETURN\n");
1326 }
1327 if (le16_to_cpu(fid->descTag.tagIdent) == TAG_IDENT_FID) {
1328 dwarn("FID found (%d)\n",*pos);
1329 flen = 38 + le16_to_cpu(fid->lengthOfImpUse) + fid->lengthFileIdent;
1330 padding = 4 * ((le16_to_cpu(fid->lengthOfImpUse) + fid->lengthFileIdent + 38 + 3)/4) - (le16_to_cpu(fid->lengthOfImpUse) + fid->lengthFileIdent + 38);
1331
1332 dbg("lengthOfImpUse: %d\n", fid->lengthOfImpUse);
1333 dbg("flen+padding: %d\n", flen+padding);
1334 if(crc(fid, flen + padding)) {
1335 err("FID CRC failed.\n");
1336 return -5;
1337 warn("DISABLED ERROR RETURN\n");
1338 }
1339 dbg("FID: ImpUseLen: %d\n", fid->lengthOfImpUse);
1340 dbg("FID: FilenameLen: %d\n", fid->lengthFileIdent);
1341 if(fid->lengthFileIdent == 0) {
1342 dbg("ROOT directory\n");
1343 } else {
1344 char *namebuf = calloc(1,256*2);
1345 memset(namebuf, 0, 256*2);
1346 int size = decode_utf8(fid->fileIdent, namebuf, fid->lengthFileIdent);
1347 dbg("Size: %d\n", size);
1348 dbg("%sFilename: %s\n", depth2str(depth), namebuf/*fid->fileIdent*/);
1349 info.filename = namebuf/*(char *)fid->fileIdent+1*/;
1350 }
1351
1352 dbg("Tag Serial Num: %d\n", fid->descTag.tagSerialNum);
1353 if(stats->AVDPSerialNum != fid->descTag.tagSerialNum) {
1354 err("(%s) Tag Serial Number differs.\n", info.filename);
1355 uint8_t fixsernum = autofix;
1356 if(interactive) {
1357 if(prompt("Fix it? [Y/n] ")) {
1358 fixsernum = 1;
1359 }
1360 }
1361 if(fixsernum) {
1362 fid->descTag.tagSerialNum = stats->AVDPSerialNum;
1363 fid->descTag.descCRC = calculate_crc(fid, flen+padding);
1364 fid->descTag.tagChecksum = calculate_checksum(fid->descTag);
1365 struct fileEntry *fe = (struct fileEntry *)(dev + (lsn) * stats->blocksize);
1366 struct extendedFileEntry *efe = (struct extendedFileEntry *)(dev + (lsn) * stats->blocksize);
1367 if(efe->descTag.tagIdent == TAG_IDENT_EFE) {
1368 efe->descTag.descCRC = calculate_crc(efe, sizeof(struct extendedFileEntry) + le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs));
1369 efe->descTag.tagChecksum = calculate_checksum(efe->descTag);
1370 } else if(efe->descTag.tagIdent == TAG_IDENT_FE) {
1371 fe->descTag.descCRC = calculate_crc(fe, sizeof(struct fileEntry) + le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs));
1372 fe->descTag.tagChecksum = calculate_checksum(fe->descTag);
1373 } else {
1374 err("(%s) FID parent FE not found.\n", info.filename);
1375 }
1376 imp("(%s) Tag Serial Number was fixed.\n", info.filename);
1377 *status |= 1;
1378 } else {
1379 *status |= 4;
1380 }
1381 }
1382
1383 dbg("FileVersionNum: %d\n", fid->fileVersionNum);
1384
1385 info.fileCharacteristics = fid->fileCharacteristics;
1386 if((fid->fileCharacteristics & FID_FILE_CHAR_DELETED) == 0) { //NOT deleted, continue
1387 dbg("ICB: LSN: %d, length: %d\n", fid->icb.extLocation.logicalBlockNum + lsnBase, fid->icb.extLength);
1388 dbg("ROOT ICB: LSN: %d\n", disc->udf_fsd->rootDirectoryICB.extLocation.logicalBlockNum + lsnBase);
1389
1390 if(*pos == 0) {
1391 dbg("Parent. Not Following this one\n");
1392 }else if(fid->icb.extLocation.logicalBlockNum + lsnBase == lsn) {
1393 dbg("Self. Not following this one\n");
1394 } else if(fid->icb.extLocation.logicalBlockNum + lsnBase == disc->udf_fsd->rootDirectoryICB.extLocation.logicalBlockNum + lsnBase) {
1395 dbg("ROOT. Not following this one.\n");
1396 } else {
1397 uint32_t uuid = 0;
1398 memcpy(&uuid, (fid->icb).impUse+2, sizeof(uint32_t));
1399 dbg("UUID: %d\n", uuid);
1400 if(stats->maxUUID < uuid) {
1401 stats->maxUUID = uuid;
1402 dwarn("New MAX UUID\n");
1403 }
1404 int fixuuid = 0;
1405 if(uuid == 0) {
1406 err("(%s) FID Unique ID is 0. There should be %d.\n", info.filename, stats->actUUID);
1407 if(interactive) {
1408 if(prompt("Fix it? [Y/n] ")) {
1409 fixuuid = 1;
1410 } else {
1411 *status |= 4;
1412 }
1413 }
1414 if(autofix) {
1415 fixuuid = 1;
1416 } else {
1417 *status |= 4;
1418 }
1419 if(fixuuid) {
1420 uuid = stats->actUUID;
1421 stats->maxUUID = uuid;
1422 stats->actUUID++;
1423 seq->lvid.error |= E_UUID;
1424 fid->icb.impUse[2] = uuid;
1425 fid->descTag.descCRC = calculate_crc(fid, flen+padding);
1426 fid->descTag.tagChecksum = calculate_checksum(fid->descTag);
1427 dbg("Location: %d\n", fid->descTag.tagLocation);
1428 struct fileEntry *fe = (struct fileEntry *)(dev + (lsn) * stats->blocksize);
1429 struct extendedFileEntry *efe = (struct extendedFileEntry *)(dev + (lsn) * stats->blocksize);
1430 if(efe->descTag.tagIdent == TAG_IDENT_EFE) {
1431 efe->descTag.descCRC = calculate_crc(efe, sizeof(struct extendedFileEntry) + le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs));
1432 efe->descTag.tagChecksum = calculate_checksum(efe->descTag);
1433 } else if(efe->descTag.tagIdent == TAG_IDENT_FE) {
1434 fe->descTag.descCRC = calculate_crc(fe, sizeof(struct fileEntry) + le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs));
1435 fe->descTag.tagChecksum = calculate_checksum(fe->descTag);
1436 } else {
1437
1438 }
1439 imp("(%s) UUID was fixed.\n", info.filename);
1440 *status |= 1;
1441 }
1442 }
1443 dbg("ICB to follow.\n");
1444 int tmp_status = get_file(dev, disc, lbnlsn, (fid->icb).extLocation.logicalBlockNum + lsnBase, stats, depth, uuid, info, seq);
1445 if(tmp_status == 32) { //32 means delete this FID
1446 fid->fileCharacteristics |= FID_FILE_CHAR_DELETED; //Set deleted flag
1447 memset(&(fid->icb), 0, sizeof(long_ad)); //clear ICB according ECMA-167r3, 4/14.4.5
1448 fid->descTag.descCRC = calculate_crc(fid, flen+padding);
1449 fid->descTag.tagChecksum = calculate_checksum(fid->descTag);
1450 dbg("Location: %d\n", fid->descTag.tagLocation);
1451 struct fileEntry *fe = (struct fileEntry *)(dev + (fid->descTag.tagLocation + lbnlsn) * stats->blocksize);
1452 struct extendedFileEntry *efe = (struct extendedFileEntry *)(dev + (fid->descTag.tagLocation + lbnlsn) * stats->blocksize);
1453 if(efe->descTag.tagIdent == TAG_IDENT_EFE) {
1454 efe->descTag.descCRC = calculate_crc(efe, sizeof(struct extendedFileEntry) + le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs));
1455 efe->descTag.tagChecksum = calculate_checksum(efe->descTag);
1456 } else if(efe->descTag.tagIdent == TAG_IDENT_EFE) {
1457 fe->descTag.descCRC = calculate_crc(fe, sizeof(struct fileEntry) + le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs));
1458 fe->descTag.tagChecksum = calculate_checksum(fe->descTag);
1459 } else {
1460 err("(%s) FID parent FE not found.\n", info.filename);
1461 }
1462 imp("(%s) Unifinished file was removed.\n", info.filename);
1463
1464 tmp_status = 1;
1465 }
1466 *status |= tmp_status;
1467 dbg("Return from ICB\n");
1468 }
1469 } else {
1470 dbg("DELETED FID\n");
1471 print_file_info(info, depth);
1472 }
1473 dbg("Len: %d, padding: %d\n", flen, padding);
1474 *pos = *pos + flen + padding;
1475 note("\n");
1476 } else {
1477 msg("Ident: %x\n", le16_to_cpu(fid->descTag.tagIdent));
1478 uint8_t *fidarray = (uint8_t *)fid;
1479 for(int i=0; i<80;) {
1480 for(int j=0; j<8; j++, i++) {
1481 note("%02x ", fidarray[i]);
1482 }
1483 note("\n");
1484 }
1485 return 1;
1486 }
1487
1488 free(info.filename);
1489 return 0;
1490 }
1491
1503 void increment_used_space(struct filesystemStats *stats, uint64_t increment, uint32_t position) {
1504 stats->usedSpace += (increment % stats->blocksize == 0 ? increment/stats->blocksize : increment/stats->blocksize+1)*stats->blocksize;
1505 markUsedBlock(stats, position, increment % stats->blocksize == 0 ? increment/stats->blocksize : increment/stats->blocksize+1, MARK_BLOCK);
1506 #if DEBUG
1507 uint64_t bits = count_used_bits(stats);
1508 dwarn("INCREMENT to %d (%d) / (%d)\n", stats->usedSpace, stats->usedSpace/stats->blocksize, bits);
1509 #endif
1510 }
1511
1523 void decrement_used_space(struct filesystemStats *stats, uint64_t increment, uint32_t position) {
1524 stats->usedSpace -= (increment % stats->blocksize == 0 ? increment/stats->blocksize : increment/stats->blocksize+1)*stats->blocksize;
1525 markUsedBlock(stats, position, increment % stats->blocksize == 0 ? increment/stats->blocksize : increment/stats->blocksize+1, UNMARK_BLOCK);
1526 #if DEBUG
1527 uint64_t bits = count_used_bits(stats);
1528 dwarn("DECREMENT to %d (%d) / (%d)\n", stats->usedSpace, stats->usedSpace/stats->blocksize, bits);
1529 #endif
1530 }
1531
1557 uint8_t get_file(const uint8_t *dev, const struct udf_disc *disc, uint32_t lbnlsn, uint32_t lsn, struct filesystemStats *stats, uint32_t depth, uint32_t uuid, struct fileInfo info, vds_sequence_t *seq ) {
1558 tag descTag;
1559 struct fileIdentDesc *fid;
1560 struct fileEntry *fe;
1561 struct extendedFileEntry *efe;
1562 int vds = -1;
1563
1564 if((vds=get_correct(seq, TAG_IDENT_LVD)) < 0) {
1565 err("No correct LVD found. Aborting.\n");
1566 return 4;
1567 }
1568
1569 uint32_t lbSize = le32_to_cpu(disc->udf_lvd[vds]->logicalBlockSize);
1570 uint32_t lsnBase = lbnlsn;
1571 uint32_t flen, padding;
1572 uint8_t dir = 0;
1573 uint8_t status = 0;
1574
1575 dwarn("\n(%d) ---------------------------------------------------\n", lsn);
1576
1577 descTag = *(tag *)(dev+lbSize*lsn);
1578 if(!checksum(descTag)) {
1579 err("Tag checksum failed. Unable to continue.\n");
1580 return 4;
1581 }
1582
1583 dbg("global FE increment.\n");
1584 dbg("usedSpace: %d\n", stats->usedSpace);
1585 increment_used_space(stats, lbSize, lsn-lbnlsn);
1586 dbg("usedSpace: %d\n", stats->usedSpace);
1587 switch(le16_to_cpu(descTag.tagIdent)) {
1588 case TAG_IDENT_FE:
1589 case TAG_IDENT_EFE:
1590 dir = 0;
1591 fe = (struct fileEntry *)(dev+lbSize*lsn);
1592 efe = (struct extendedFileEntry *)fe;
1593 uint8_t ext = 0;
1594
1595 if(le16_to_cpu(descTag.tagIdent) == TAG_IDENT_EFE) {
1596 dwarn("[EFE]\n");
1597 if(crc(efe, sizeof(struct extendedFileEntry) + le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs))) {
1598 err("EFE CRC failed.\n");
1599 int cont = 0;
1600 if(interactive) {
1601 if(prompt("Continue with caution, yes? [Y/n] ")) {
1602 cont = 1;
1603 }
1604 }
1605 if(cont == 0) {
1606 return 4;
1607 }
1608 }
1609 ext = 1;
1610 } else {
1611 if(crc(fe, sizeof(struct fileEntry) + le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs))) {
1612 err("FE CRC failed.\n");
1613 int cont = 0;
1614 if(interactive) {
1615 if(prompt("Continue with caution, yes? [Y/n] ")) {
1616 cont = 1;
1617 }
1618 }
1619 if(cont == 0) {
1620 return 4;
1621 }
1622 }
1623 }
1624 dbg("Tag Serial Num: %d\n", descTag.tagSerialNum);
1625 if(stats->AVDPSerialNum != descTag.tagSerialNum) {
1626 err("(%s) Tag Serial Number differs.\n", info.filename);
1627 uint8_t fixsernum = autofix;
1628 if(interactive) {
1629 if(prompt("Fix it? [Y/n] ")) {
1630 fixsernum = 1;
1631 } else {
1632 status |= 4;
1633 }
1634 }
1635 if(fixsernum) {
1636 descTag.tagSerialNum = stats->AVDPSerialNum;
1637 if(ext) {
1638 efe->descTag.descCRC = calculate_crc(efe, sizeof(struct extendedFileEntry) + le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs));
1639 efe->descTag.tagChecksum = calculate_checksum(efe->descTag);
1640 } else {
1641 fe->descTag.descCRC = calculate_crc(fe, sizeof(struct fileEntry) + le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs));
1642 fe->descTag.tagChecksum = calculate_checksum(fe->descTag);
1643 }
1644 status |= 1;
1645 }
1646 }
1647 dbg("\nFE, LSN: %d, EntityID: %s ", lsn, fe->impIdent.ident);
1648 dbg("fileLinkCount: %d, LB recorded: %lu\n", fe->fileLinkCount, ext ? efe->logicalBlocksRecorded: fe->logicalBlocksRecorded);
1649 uint32_t lea = ext ? efe->lengthExtendedAttr : fe->lengthExtendedAttr;
1650 uint32_t lad = ext ? efe->lengthAllocDescs : fe->lengthAllocDescs;
1651 dbg("LEA %d, LAD %d\n", lea, lad);
1652 dbg("Information Length: %d\n", fe->informationLength);
1653
1654
1655 if((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) != ICBTAG_FLAG_AD_IN_ICB && fe->icbTag.fileType == ICBTAG_FILE_TYPE_REGULAR && (fe->informationLength % stats->blocksize == 0? fe->informationLength/stats->blocksize : fe->informationLength/stats->blocksize + 1) != (ext ? efe->logicalBlocksRecorded : fe->logicalBlocksRecorded)) {
1656 dbg("InfLenBlocks: %d\n", fe->informationLength % stats->blocksize == 0? fe->informationLength/stats->blocksize : fe->informationLength/stats->blocksize + 1);
1657 dbg("BlocksRecord: %d\n", ext ? efe->logicalBlocksRecorded : fe->logicalBlocksRecorded);
1658 err("(%s) File size mismatch. Probably unfinished file write.\n", info.filename);
1659 int fixit = 0;
1660
1661 if(interactive) {
1662 if(prompt("Fix it? [Y/n] ")) {
1663 fixit = 1;
1664 } else {
1665 status |= 4;
1666 }
1667 } else if(autofix) {
1668 fixit = 1;
1669 }
1670
1671 if(fixit) {
1672 imp("Removing unfinished file...\n");
1673 dbg("global FE decrement.\n");
1674 dbg("usedSpace: %d\n", stats->usedSpace);
1675 decrement_used_space(stats, lbSize, lsn-lbnlsn);
1676 dbg("usedSpace: %d\n", stats->usedSpace);
1677 uint8_t *blank;
1678 blank = malloc(stats->blocksize);
1679 memcpy(fe, blank, stats->blocksize);
1680 free(blank);
1681 return 32;
1682 }
1683 }
1684
1685 info.size = fe->informationLength;
1686 info.fileType = fe->icbTag.fileType;
1687 info.permissions = fe->permissions;
1688 dbg("Permissions: 0x%04x : 0x%04x\n", info.permissions, fe->permissions);
1689
1690 switch(fe->icbTag.fileType) {
1691 case ICBTAG_FILE_TYPE_UNDEF:
1692 dbg("Filetype: undef\n");
1693 break;
1694 case ICBTAG_FILE_TYPE_USE:
1695 dbg("Filetype: USE\n");
1696 break;
1697 case ICBTAG_FILE_TYPE_PIE:
1698 dbg("Filetype: PIE\n");
1699 break;
1700 case ICBTAG_FILE_TYPE_IE:
1701 dbg("Filetype: IE\n");
1702 break;
1703 case ICBTAG_FILE_TYPE_DIRECTORY:
1704 dbg("Filetype: DIR\n");
1705 stats->countNumOfDirs ++;
1706 // stats->usedSpace += lbSize;
1707 //increment_used_space(stats, lbSize);
1708 dir = 1;
1709 break;
1710 case ICBTAG_FILE_TYPE_REGULAR:
1711 dbg("Filetype: REGULAR\n");
1712 stats->countNumOfFiles ++;
1713 // stats->usedSpace += lbSize;
1714 break;
1715 case ICBTAG_FILE_TYPE_BLOCK:
1716 dbg("Filetype: BLOCK\n");
1717 stats->countNumOfFiles ++;
1718 break;
1719 case ICBTAG_FILE_TYPE_CHAR:
1720 dbg("Filetype: CHAR\n");
1721 stats->countNumOfFiles ++;
1722 break;
1723 case ICBTAG_FILE_TYPE_EA:
1724 dbg("Filetype: EA\n");
1725 break;
1726 case ICBTAG_FILE_TYPE_FIFO:
1727 dbg("Filetype: FIFO\n");
1728 stats->countNumOfFiles ++;
1729 break;
1730 case ICBTAG_FILE_TYPE_SOCKET:
1731 dbg("Filetype: SOCKET\n");
1732 break;
1733 case ICBTAG_FILE_TYPE_TE:
1734 dbg("Filetype: TE\n");
1735 break;
1736 case ICBTAG_FILE_TYPE_SYMLINK:
1737 dbg("Filetype: SYMLINK\n");
1738 stats->countNumOfFiles ++;
1739 break;
1740 case ICBTAG_FILE_TYPE_STREAMDIR:
1741 dbg("Filetype: STRAMDIR\n");
1742 //stats->usedSpace += lbSize;
1743 break;
1744 default:
1745 dbg("Unknown filetype\n");
1746 break;
1747 }
1748
1749 dbg("numEntries: %d\n", fe->icbTag.numEntries);
1750 dbg("Parent ICB loc: %d\n", fe->icbTag.parentICBLocation.logicalBlockNum);
1751
1752 double cts = 0;
1753 if((cts = compare_timestamps(stats->LVIDtimestamp, ext ? efe->modificationTime : fe->modificationTime)) < 0) {
1754 err("(%s) File timestamp is later than LVID timestamp. LVID need to be fixed.\n", info.filename);
1755 #ifdef DEBUG
1756 err("CTS: %f\n", cts);
1757 #endif
1758 seq->lvid.error |= E_TIMESTAMP;
1759 }
1760 info.modTime = ext ? efe->modificationTime : fe->modificationTime;
1761
1762
1763 uint64_t feUUID = (ext ? efe->uniqueID : fe->uniqueID);
1764 dbg("Unique ID: FE: %d FID: %d\n", (feUUID), uuid);
1765 int fixuuid = 0;
1766 if(uuid != feUUID) {
1767 err("(%s) FE Unique ID differs from FID Unique ID.\n", info.filename);
1768 if(interactive) {
1769 if(prompt("Fix it (set Unique ID to %d, value according FID)? [Y/n] ", uuid) != 0) {
1770 fixuuid = 1;
1771 } else {
1772 status |= 4;
1773 }
1774 }
1775 if(autofix) {
1776 fixuuid = 1;
1777 }
1778 }
1779 if(fixuuid) {
1780 if(ext) {
1781 efe->uniqueID = uuid;
1782 efe->descTag.descCRC = calculate_crc(efe, sizeof(struct extendedFileEntry) + le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs));
1783 efe->descTag.tagChecksum = calculate_checksum(efe->descTag);
1784 } else {
1785 fe->uniqueID = uuid;
1786 fe->descTag.descCRC = calculate_crc(fe, sizeof(struct fileEntry) + le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs));
1787 fe->descTag.tagChecksum = calculate_checksum(fe->descTag);
1788 }
1789 status |= 1;
1790 }
1791
1792 dbg("FC: %04d DC: %04d ", stats->countNumOfFiles, stats->countNumOfDirs);
1793 print_file_info(info, depth);
1794
1795 uint8_t fid_inspected = 0;
1796 uint8_t *allocDescs = (ext ? efe->allocDescs : fe->allocDescs) + lea;
1797 if((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT) {
1798 if(dir) {
1799 fid_inspected = 1;
1800 translate_fid(dev, disc, lbnlsn, lsn, allocDescs, lad, ICBTAG_FLAG_AD_SHORT, stats, depth, seq, &status);
1801 } else {
1802 dbg("SHORT\n");
1803 dbg("LAD: %d, N: %d, rest: %d\n", lad, lad/sizeof(short_ad), lad%sizeof(short_ad));
1804 for(int si = 0; si < lad/sizeof(short_ad); si++) {
1805 dwarn("SHORT #%d\n", si);
1806 short_ad *sad = (short_ad *)(allocDescs + si*sizeof(short_ad));
1807 dbg("ExtLen: %d, ExtLoc: %d\n", sad->extLength, sad->extPosition);
1808
1809 dbg("usedSpace: %d\n", stats->usedSpace);
1810 uint32_t usedsize = sad->extLength;
1811 dbg("Used size: %d\n", usedsize);
1812 increment_used_space(stats, usedsize, sad->extPosition);
1813 lsn = lsn + sad->extLength/lbSize;
1814 dbg("LSN: %d, ExtLocOrig: %d\n", lsn, sad->extPosition);
1815 dbg("usedSpace: %d\n", stats->usedSpace);
1816 dwarn("Size: %d, Blocks: %d\n", usedsize, usedsize/lbSize);
1817 }
1818 }
1819 } else if((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_LONG) {
1820 if(dir) {
1821 fid_inspected = 1;
1822 translate_fid(dev, disc, lbnlsn, lsn, allocDescs, lad, ICBTAG_FLAG_AD_LONG, stats, depth, seq, &status);
1823 } else {
1824 for(int si = 0; si < lad/sizeof(long_ad); si++) {
1825 dbg("LONG\n");
1826 long_ad *lad = (long_ad *)(allocDescs + si*sizeof(long_ad));
1827 dbg("ExtLen: %d, ExtLoc: %d\n", lad->extLength/lbSize, lad->extLocation.logicalBlockNum+lsnBase);
1828
1829 dbg("usedSpace: %d\n", stats->usedSpace);
1830 uint32_t usedsize = lad->extLength;//(fe->informationLength%lbSize == 0 ? fe->informationLength : (fe->informationLength + lbSize - fe->informationLength%lbSize));
1831 increment_used_space(stats, usedsize, lad->extLocation.logicalBlockNum);
1832 lsn = lsn + lad->extLength/lbSize;
1833 dbg("LSN: %d\n", lsn);
1834 dbg("usedSpace: %d\n", stats->usedSpace);
1835 dwarn("Size: %d, Blocks: %d\n", usedsize, usedsize/lbSize);
1836 }
1837 }
1838 } else if((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_EXTENDED) {
1839 if(dir) {
1840 fid_inspected = 1;
1841 translate_fid(dev, disc, lbnlsn, lsn, allocDescs, lad, ICBTAG_FLAG_AD_EXTENDED, stats, depth, seq, &status);
1842 } else {
1843 err("EAD found. Please report.\n");
1844 }
1845 } else if((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB) {
1846 dbg("AD in ICB\n");
1847 struct extendedAttrHeaderDesc eahd;
1848 struct genericFormat *gf;
1849 struct impUseExtAttr *impAttr;
1850 struct appUseExtAttr *appAttr;
1851 tag *descTag;
1852 uint8_t *array;
1853 uint8_t *base = NULL;
1854 if(ext) {
1855 eahd = *(struct extendedAttrHeaderDesc *)(efe + sizeof(struct extendedFileEntry) + efe->lengthExtendedAttr);
1856 descTag = (tag *)((uint8_t *)(efe) + sizeof(struct extendedFileEntry) + efe->lengthExtendedAttr);
1857 dbg("efe: %p, POS: %d, descTag: %p\n",efe, sizeof(struct extendedFileEntry) + efe->lengthExtendedAttr, descTag);
1858 } else {
1859 eahd = *(struct extendedAttrHeaderDesc *)(fe + sizeof(struct fileEntry) + fe->lengthExtendedAttr);
1860 descTag = (tag *)((uint8_t *)(fe) + sizeof(struct fileEntry) + fe->lengthExtendedAttr);
1861 dbg("fe: %p, POS: %d, descTag: %p\n", fe, sizeof(struct fileEntry) + fe->lengthExtendedAttr, descTag);
1862 }
1863 array = (uint8_t *)descTag;
1864
1865 if(descTag->tagIdent == TAG_IDENT_EAHD) {
1866 base = (ext ? efe->allocDescs : fe->allocDescs) + eahd.appAttrLocation;
1867
1868 dbg("impAttrLoc: %d, appAttrLoc: %d\n", eahd.impAttrLocation, eahd.appAttrLocation);
1869 gf = (struct genericFormat *)(fe->allocDescs + eahd.impAttrLocation);
1870
1871 dbg("AttrType: %d\n", gf->attrType);
1872 dbg("AttrLength: %d\n", gf->attrLength);
1873 if(gf->attrType == EXTATTR_IMP_USE) {
1874 impAttr = (struct impUseExtAttr *)gf;
1875 dbg("ImpUseLength: %d\n", impAttr->impUseLength);
1876 dbg("ImpIdent: Flags: 0x%02x\n", impAttr->impIdent.flags);
1877 dbg("ImpIdent: Ident: %s\n", impAttr->impIdent.ident);
1878 dbg("ImpIdent: IdentSuffix: ");
1879 for(int k=0; k<8; k++) {
1880 note("0x%02x ", impAttr->impIdent.identSuffix[k]);
1881 }
1882 note("\n");
1883 } else {
1884 err("EAHD mismatch. Expected IMP, found %d\n", gf->attrType);
1885 }
1886
1887 gf = (struct genericFormat *)(fe->allocDescs + eahd.appAttrLocation);
1888
1889 dbg("AttrType: %d\n", gf->attrType);
1890 dbg("AttrLength: %d\n", gf->attrLength);
1891 if(gf->attrType == EXTATTR_APP_USE) {
1892 appAttr = (struct appUseExtAttr *)gf;
1893 } else {
1894 err("EAHD mismatch. Expected APP, found %d\n", gf->attrType);
1895
1896 fid_inspected = 1;
1897 for(uint32_t pos=0; ; ) {
1898 if(inspect_fid(dev, disc, lbnlsn, lsn, base, &pos, stats, depth, seq, &status) != 0) {
1899 dbg("FID inspection over\n");
1900 break;
1901 }
1902 }
1903 }
1904 } else {
1905 dwarn("ID: 0x%02x\n",descTag->tagIdent);
1906 }
1907
1908 } else {
1909 dbg("ICB TAG->flags: 0x%02x\n", fe->icbTag.flags);
1910 }
1911
1912 // We can assume that directory have one or more FID inside.
1913 // FE have inside long_ad/short_ad.
1914 if(dir && fid_inspected == 0) {
1915 if(ext) {
1916 dbg("[EFE DIR] lengthExtendedAttr: %d\n", efe->lengthExtendedAttr);
1917 dbg("[EFE DIR] lengthAllocDescs: %d\n", efe->lengthAllocDescs);
1918 for(uint32_t pos=0; pos < efe->lengthAllocDescs; ) {
1919 if(inspect_fid(dev, disc, lbnlsn, lsn, efe->allocDescs + efe->lengthExtendedAttr, &pos, stats, depth+1, seq, &status) != 0) {
1920 break;
1921 }
1922 }
1923 } else {
1924 dbg("[FE DIR] lengthExtendedAttr: %d\n", fe->lengthExtendedAttr);
1925 dbg("[FE DIR] lengthAllocDescs: %d\n", fe->lengthAllocDescs);
1926 for(uint32_t pos=0; pos < fe->lengthAllocDescs; ) {
1927 if(inspect_fid(dev, disc, lbnlsn, lsn, fe->allocDescs + fe->lengthExtendedAttr, &pos, stats, depth+1, seq, &status) != 0) {
1928 break;
1929 }
1930 }
1931 }
1932 }
1933 break;
1934 default:
1935 err("IDENT: %x, LSN: %d, addr: 0x%x\n", descTag.tagIdent, lsn, lsn*lbSize);
1936 }
1937 return status;
1938 }
1939
1953 uint8_t get_file_structure(const uint8_t *dev, const struct udf_disc *disc, uint32_t lbnlsn, struct filesystemStats *stats, vds_sequence_t *seq ) {
1954 struct fileEntry *file;
1955 struct fileIdentDesc *fid;
1956 tag descTag;
1957 uint32_t lsn, slsn;
1958
1959 uint8_t ptLength = 1;
1960 uint32_t extLoc;
1961 char *filename;
1962 uint16_t pos = 0;
1963 uint32_t lsnBase = lbnlsn;
1964 int status = 0;
1965 uint32_t elen = 0, selen = 0;
1966
1967 int vds = -1;
1968 if((vds=get_correct(seq, TAG_IDENT_LVD)) < 0) {
1969 err("No correct LVD found. Aborting.\n");
1970 return 4;
1971 }
1972 dbg("VDS used: %d\n", vds);
1973 dbg("Disc ptr: %p, LVD ptr: %p\n", disc, disc->udf_lvd[vds]);
1974 dbg("Disc ptr: %p, FSD ptr: %p\n", disc, disc->udf_fsd);
1975
1976 uint32_t lbSize = le32_to_cpu(disc->udf_lvd[vds]->logicalBlockSize);
1977 // Go to ROOT ICB
1978 lb_addr icbloc = lelb_to_cpu(disc->udf_fsd->rootDirectoryICB.extLocation);
1979 // Get Stream Dir ICB
1980 lb_addr sicbloc = lelb_to_cpu(disc->udf_fsd->streamDirectoryICB.extLocation);
1981
1982 lsn = icbloc.logicalBlockNum+lsnBase;
1983 slsn = sicbloc.logicalBlockNum+lsnBase;
1984 elen = disc->udf_fsd->rootDirectoryICB.extLength;
1985 selen = disc->udf_fsd->streamDirectoryICB.extLength;
1986 dbg("ROOT LSN: %d, len: %d, partition: %d\n", lsn, elen, icbloc.partitionReferenceNum);
1987 dbg("STREAM LSN: %d len: %d, partition: %d\n", slsn, selen, sicbloc.partitionReferenceNum);
1988
1989 dbg("Used space offset: %d\n", stats->usedSpace);
1990 struct fileInfo info = {0};
1991
1992 if(selen > 0) {
1993 msg("\nStream file tree\n----------------\n");
1994 status |= get_file(dev, disc, lbnlsn, slsn, stats, 0, 0, info, seq);
1995 }
1996 if(elen > 0) {
1997 msg("\nMedium file tree\n----------------\n");
1998 status |= get_file(dev, disc, lbnlsn, lsn, stats, 0, 0, info, seq);
1999 }
2000 return status;
2001 }
2002
2014 int append_error(vds_sequence_t *seq, uint16_t tagIdent, vds_type_e vds, uint8_t error) {
2015 for(int i=0; i<VDS_STRUCT_AMOUNT; ++i) {
2016 if(vds == MAIN_VDS) {
2017 if(seq->main[i].tagIdent == tagIdent) {
2018 seq->main[i].error |= error;
2019 return 0;
2020 }
2021 } else {
2022 if(seq->reserve[i].tagIdent == tagIdent) {
2023 seq->reserve[i].error |= error;
2024 return 0;
2025 }
2026 }
2027 }
2028 return -1;
2029 }
2030
2040 uint32_t get_tag_location(vds_sequence_t *seq, uint16_t tagIdent, vds_type_e vds) {
2041 for(int i=0; i<VDS_STRUCT_AMOUNT; ++i) {
2042 if(vds == MAIN_VDS) {
2043 if(seq->main[i].tagIdent == tagIdent) {
2044 return seq->main[i].tagLocation;
2045 }
2046 } else {
2047 if(seq->reserve[i].tagIdent == tagIdent) {
2048 return seq->reserve[i].tagLocation;
2049 }
2050 }
2051 }
2052 return -1;
2053 }
2054
2066 int verify_vds(struct udf_disc *disc, vds_type_e vds, vds_sequence_t *seq) {
2067 uint8_t *data;
2068 uint16_t offset = sizeof(tag);
2069
2070 if(!checksum(disc->udf_pvd[vds]->descTag)) {
2071 err("Checksum failure at PVD[%d]\n", vds);
2072 append_error(seq, TAG_IDENT_PVD, vds, E_CHECKSUM);
2073 }
2074 if(!checksum(disc->udf_lvd[vds]->descTag)) {
2075 err("Checksum failure at LVD[%d]\n", vds);
2076 append_error(seq, TAG_IDENT_LVD, vds, E_CHECKSUM);
2077 }
2078 if(!checksum(disc->udf_pd[vds]->descTag)) {
2079 err("Checksum failure at PD[%d]\n", vds);
2080 append_error(seq, TAG_IDENT_PD, vds, E_CHECKSUM);
2081 }
2082 if(!checksum(disc->udf_usd[vds]->descTag)) {
2083 err("Checksum failure at USD[%d]\n", vds);
2084 append_error(seq, TAG_IDENT_USD, vds, E_CHECKSUM);
2085 }
2086 if(!checksum(disc->udf_iuvd[vds]->descTag)) {
2087 err("Checksum failure at IUVD[%d]\n", vds);
2088 append_error(seq, TAG_IDENT_IUVD, vds, E_CHECKSUM);
2089 }
2090 if(!checksum(disc->udf_td[vds]->descTag)) {
2091 err("Checksum failure at TD[%d]\n", vds);
2092 append_error(seq, TAG_IDENT_TD, vds, E_CHECKSUM);
2093 }
2094
2095 if(check_position(disc->udf_pvd[vds]->descTag, get_tag_location(seq, TAG_IDENT_PVD, vds))) {
2096 err("Position failure at PVD[%d]\n", vds);
2097 append_error(seq, TAG_IDENT_PVD, vds, E_POSITION);
2098 }
2099 if(check_position(disc->udf_lvd[vds]->descTag, get_tag_location(seq, TAG_IDENT_LVD, vds))) {
2100 err("Position failure at LVD[%d]\n", vds);
2101 append_error(seq, TAG_IDENT_LVD, vds, E_POSITION);
2102 }
2103 if(check_position(disc->udf_pd[vds]->descTag, get_tag_location(seq, TAG_IDENT_PD, vds))) {
2104 err("Position failure at PD[%d]\n", vds);
2105 append_error(seq, TAG_IDENT_PD, vds, E_POSITION);
2106 }
2107 if(check_position(disc->udf_usd[vds]->descTag, get_tag_location(seq, TAG_IDENT_USD, vds))) {
2108 err("Position failure at USD[%d]\n", vds);
2109 append_error(seq, TAG_IDENT_USD, vds, E_POSITION);
2110 }
2111 if(check_position(disc->udf_iuvd[vds]->descTag, get_tag_location(seq, TAG_IDENT_IUVD, vds))) {
2112 err("Position failure at IUVD[%d]\n", vds);
2113 append_error(seq, TAG_IDENT_IUVD, vds, E_POSITION);
2114 }
2115 if(check_position(disc->udf_td[vds]->descTag, get_tag_location(seq, TAG_IDENT_TD, vds))) {
2116 err("Position failure at TD[%d]\n", vds);
2117 append_error(seq, TAG_IDENT_TD, vds, E_POSITION);
2118 }
2119
2120 if(crc(disc->udf_pvd[vds], sizeof(struct primaryVolDesc))) {
2121 err("CRC error at PVD[%d]\n", vds);
2122 append_error(seq, TAG_IDENT_PVD, vds, E_CRC);
2123 }
2124 if(crc(disc->udf_lvd[vds], sizeof(struct logicalVolDesc)+disc->udf_lvd[vds]->mapTableLength)) {
2125 err("CRC error at LVD[%d]\n", vds);
2126 append_error(seq, TAG_IDENT_LVD, vds, E_CRC);
2127 }
2128 if(crc(disc->udf_pd[vds], sizeof(struct partitionDesc))) {
2129 err("CRC error at PD[%d]\n", vds);
2130 append_error(seq, TAG_IDENT_PD, vds, E_CRC);
2131 }
2132 if(crc(disc->udf_usd[vds], sizeof(struct unallocSpaceDesc)+(disc->udf_usd[vds]->numAllocDescs)*sizeof(extent_ad))) {
2133 err("CRC error at USD[%d]\n", vds);
2134 append_error(seq, TAG_IDENT_USD, vds, E_CRC);
2135 }
2136 if(crc(disc->udf_iuvd[vds], sizeof(struct impUseVolDesc))) {
2137 err("CRC error at IUVD[%d]\n", vds);
2138 append_error(seq, TAG_IDENT_IUVD, vds, E_CRC);
2139 }
2140 if(crc(disc->udf_td[vds], sizeof(struct terminatingDesc))) {
2141 err("CRC error at TD[%d]\n", vds);
2142 append_error(seq, TAG_IDENT_TD, vds, E_CRC);
2143 }
2144
2145 return 0;
2146 }
2147
2162 int copy_descriptor(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, uint32_t sourcePosition, uint32_t destinationPosition, size_t size) {
2163 tag sourceDescTag, destinationDescTag;
2164 uint8_t *destArray;
2165
2166 dbg("source: 0x%x, destination: 0x%x\n", sourcePosition, destinationPosition);
2167
2168 sourceDescTag = *(tag *)(dev+sourcePosition*sectorsize);
2169 memcpy(&destinationDescTag, &sourceDescTag, sizeof(tag));
2170 destinationDescTag.tagLocation = destinationPosition;
2171 destinationDescTag.tagChecksum = calculate_checksum(destinationDescTag);
2172
2173 dbg("srcChecksum: 0x%x, destChecksum: 0x%x\n", sourceDescTag.tagChecksum, destinationDescTag.tagChecksum);
2174
2175 destArray = calloc(1, size);
2176 memcpy(destArray, &destinationDescTag, sizeof(tag));
2177 memcpy(destArray+sizeof(tag), dev+sourcePosition*sectorsize+sizeof(tag), size-sizeof(tag));
2178
2179 memcpy(dev+destinationPosition*sectorsize, destArray, size);
2180
2181 free(destArray);
2182
2183 return 0;
2184 }
2185
2200 int write_avdp(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, size_t devsize, avdp_type_e source, avdp_type_e target) {
2201 uint64_t sourcePosition = 0;
2202 uint64_t targetPosition = 0;
2203 tag desc_tag;
2204 avdp_type_e type = target;
2205
2206 // Taget type to determine position on media
2207 if(source == 0) {
2208 sourcePosition = sectorsize*256; //First AVDP is on LSN=256
2209 } else if(source == 1) {
2210 sourcePosition = devsize-sectorsize; //Second AVDP is on last LSN
2211 } else if(source == 2) {
2212 sourcePosition = devsize-sectorsize-256*sectorsize; //Third AVDP can be at last LSN-256
2213 } else {
2214 sourcePosition = sectorsize*512; //Unclosed disc have AVDP at sector 512
2215 }
2216
2217 // Taget type to determine position on media
2218 if(target == 0) {
2219 targetPosition = sectorsize*256; //First AVDP is on LSN=256
2220 } else if(target == 1) {
2221 targetPosition = devsize-sectorsize; //Second AVDP is on last LSN
2222 } else if(target == 2) {
2223 targetPosition = devsize-sectorsize-256*sectorsize; //Third AVDP can be at last LSN-256
2224 } else {
2225 targetPosition = sectorsize*512; //Unclosed disc have AVDP at sector 512
2226 type = FIRST_AVDP; //Save it to FIRST_AVDP positon
2227 }
2228
2229 dbg("DevSize: %zu\n", devsize);
2230 dbg("Current position: %lx\n", targetPosition);
2231
2232 copy_descriptor(dev, disc, sectorsize, sourcePosition/sectorsize, targetPosition/sectorsize, sizeof(struct anchorVolDescPtr));
2233
2234 free(disc->udf_anchor[type]);
2235 disc->udf_anchor[type] = malloc(sizeof(struct anchorVolDescPtr)); // Prepare memory for AVDP
2236
2237 desc_tag = *(tag *)(dev+targetPosition);
2238
2239 if(!checksum(desc_tag)) {
2240 err("Checksum failure at AVDP[%d]\n", type);
2241 return -2;
2242 } else if(le16_to_cpu(desc_tag.tagIdent) != TAG_IDENT_AVDP) {
2243 err("AVDP not found at 0x%lx\n", targetPosition);
2244 return -4;
2245 }
2246
2247 memcpy(disc->udf_anchor[type], dev+targetPosition, sizeof(struct anchorVolDescPtr));
2248
2249 if(crc(disc->udf_anchor[type], sizeof(struct anchorVolDescPtr))) {
2250 err("CRC error at AVDP[%d]\n", type);
2251 return -3;
2252 }
2253
2254 imp("AVDP[%d] successfully written.\n", type);
2255 return 0;
2256 }
2257
2271 int fix_avdp(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, size_t devsize, avdp_type_e target) {
2272 uint64_t targetPosition = 0;
2273 tag desc_tag;
2274 avdp_type_e type = target;
2275
2276 // Taget type to determine position on media
2277 if(target == 0) {
2278 targetPosition = sectorsize*256; //First AVDP is on LSN=256
2279 } else if(target == 1) {
2280 targetPosition = devsize-sectorsize; //Second AVDP is on last LSN
2281 } else if(target == 2) {
2282 targetPosition = devsize-sectorsize-256*sectorsize; //Third AVDP can be at last LSN-256
2283 } else {
2284 targetPosition = sectorsize*512; //Unclosed disc have AVDP at sector 512
2285 type = FIRST_AVDP; //Save it to FIRST_AVDP positon
2286 }
2287
2288 dbg("DevSize: %zu\n", devsize);
2289 dbg("Current position: %lx\n", targetPosition);
2290
2291 desc_tag = *(tag *)(dev+targetPosition);
2292
2293 if(!checksum(desc_tag)) {
2294 err("Checksum failure at AVDP[%d]\n", type);
2295 return -2;
2296 } else if(le16_to_cpu(desc_tag.tagIdent) != TAG_IDENT_AVDP) {
2297 err("AVDP not found at 0x%lx\n", targetPosition);
2298 return -4;
2299 }
2300
2301 if(disc->udf_anchor[type]->mainVolDescSeqExt.extLength > disc->udf_anchor[type]->reserveVolDescSeqExt.extLength) { //main is bigger
2302 if(disc->udf_anchor[type]->mainVolDescSeqExt.extLength >= 16*sectorsize) { //and is big enough
2303 disc->udf_anchor[type]->reserveVolDescSeqExt.extLength = disc->udf_anchor[type]->mainVolDescSeqExt.extLength;
2304 }
2305 } else { //reserve is bigger
2306 if(disc->udf_anchor[type]->reserveVolDescSeqExt.extLength >= 16*sectorsize) { //and is big enough
2307 disc->udf_anchor[type]->mainVolDescSeqExt.extLength = disc->udf_anchor[type]->reserveVolDescSeqExt.extLength;
2308 }
2309 }
2310 disc->udf_anchor[type]->descTag.descCRC = calculate_crc(disc->udf_anchor[type], sizeof(struct anchorVolDescPtr));
2311 disc->udf_anchor[type]->descTag.tagChecksum = calculate_checksum(disc->udf_anchor[type]->descTag);
2312
2313 memcpy(dev+targetPosition, disc->udf_anchor[type], sizeof(struct anchorVolDescPtr));
2314
2315 imp("AVDP[%d] Extent Length successfully fixed.\n", type);
2316 return 0;
2317 }
2318
2326 char * descriptor_name(uint16_t descIdent) {
2327 switch(descIdent) {
2328 case TAG_IDENT_PVD:
2329 return "PVD";
2330 case TAG_IDENT_LVD:
2331 return "LVD";
2332 case TAG_IDENT_PD:
2333 return "PD";
2334 case TAG_IDENT_USD:
2335 return "USD";
2336 case TAG_IDENT_IUVD:
2337 return "IUVD";
2338 case TAG_IDENT_TD:
2339 return "TD";
2340 case TAG_IDENT_AVDP:
2341 return "AVDP";
2342 case TAG_IDENT_LVID:
2343 return "LVID";
2344 default:
2345 return "Unknown";
2346 }
2347 }
2348
2362 int fix_vds(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, avdp_type_e source, vds_sequence_t *seq) {
2363 uint32_t position_main, position_reserve;
2364 int8_t counter = 0;
2365 tag descTag;
2366 uint8_t fix=0;
2367 uint8_t status = 0;
2368
2369 // Go to first address of VDS
2370 position_main = (disc->udf_anchor[source]->mainVolDescSeqExt.extLocation);
2371 position_reserve = (disc->udf_anchor[source]->reserveVolDescSeqExt.extLocation);
2372
2373
2374 msg("\nVDS verification status\n-----------------------\n");
2375
2376 for(int i=0; i<VDS_STRUCT_AMOUNT; ++i) {
2377 if(seq->main[i].error != 0 && seq->reserve[i].error != 0) {
2378 //Both descriptors are broken
2379 //TODO It can be possible to reconstruct some descriptors, but not all.
2380 err("[%d] Both descriptors are broken. Maybe not able to continue later.\n",i);
2381 } else if(seq->main[i].error != 0) {
2382 //Copy Reserve -> Main
2383 if(interactive) {
2384 fix = prompt("%s is broken. Fix it? [Y/n]", descriptor_name(seq->reserve[i].tagIdent));
2385 } else if (autofix) {
2386 fix = 1;
2387 }
2388
2389 //int copy_descriptor(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, uint32_t sourcePosition, uint32_t destinationPosition, size_t amount);
2390 if(fix) {
2391 warn("[%d] Fixing Main %s\n",i,descriptor_name(seq->reserve[i].tagIdent));
2392 warn("sectorsize: %d\n", sectorsize);
2393 warn("src pos: 0x%x\n", position_reserve + i);
2394 warn("dest pos: 0x%x\n", position_main + i);
2395 // memcpy(position_main + i*sectorsize, position_reserve + i*sectorsize, sectorsize);
2396 copy_descriptor(dev, disc, sectorsize, position_reserve + i, position_main + i, sectorsize);
2397 status |= 1;
2398 } else {
2399 err("[%i] %s is broken.\n", i,descriptor_name(seq->reserve[i].tagIdent));
2400 status |= 4;
2401 }
2402 fix = 0;
2403 } else if(seq->reserve[i].error != 0) {
2404 //Copy Main -> Reserve
2405 if(interactive) {
2406 fix = prompt("%s is broken. Fix it? [Y/n]", descriptor_name(seq->main[i].tagIdent));
2407 } else if (autofix) {
2408 fix = 1;
2409 }
2410
2411 if(fix) {
2412 warn("[%i] Fixing Reserve %s\n", i,descriptor_name(seq->main[i].tagIdent));
2413 copy_descriptor(dev, disc, sectorsize, position_reserve + i, position_main + i, sectorsize);
2414 status |= 1;
2415 } else {
2416 err("[%i] %s is broken.\n", i,descriptor_name(seq->main[i].tagIdent));
2417 status |= 4;
2418 }
2419 fix = 0;
2420 } else {
2421 msg("[%d] %s is fine. No fixing needed.\n", i, descriptor_name(seq->main[i].tagIdent));
2422 }
2423 if(seq->main[i].tagIdent == TAG_IDENT_TD)
2424 break;
2425 }
2426
2427
2428 return status;
2429 }
2430
2431 static const unsigned char BitsSetTable256[256] =
2432 {
2433 #define B2(n) n, n+1, n+1, n+2
2434 #define B4(n) B2(n), B2(n+1), B2(n+1), B2(n+2)
2435 #define B6(n) B4(n), B4(n+1), B4(n+1), B4(n+2)
2436 B6(0), B6(1), B6(1), B6(2)
2437 };
2438
2455 int fix_pd(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, struct filesystemStats *stats, vds_sequence_t *seq) {
2456 int vds = -1;
2457 if((vds=get_correct(seq, TAG_IDENT_PD)) < 0) {
2458 err("No correct PD found. Aborting.\n");
2459 return 4;
2460 }
2461 struct partitionHeaderDesc *phd = (struct partitionHeaderDesc *)(disc->udf_pd[vds]->partitionContentsUse);
2462 dbg("[USD] UST pos: %d, len: %d\n", phd->unallocSpaceTable.extPosition, phd->unallocSpaceTable.extLength);
2463 dbg("[USD] USB pos: %d, len: %d\n", phd->unallocSpaceBitmap.extPosition, phd->unallocSpaceBitmap.extLength);
2464 dbg("[USD] FST pos: %d, len: %d\n", phd->freedSpaceTable.extPosition, phd->freedSpaceTable.extLength);
2465 dbg("[USD] FSB pos: %d, len: %d\n", phd->freedSpaceBitmap.extPosition, phd->freedSpaceBitmap.extLength);
2466
2467 if(phd->unallocSpaceTable.extLength > 0) {
2468 //Unhandled. Not found on any medium.
2469 err("[USD] Unallocated Space Table is unhandled. Skipping.\n");
2470 }
2471 if(phd->freedSpaceTable.extLength > 0) {
2472 //Unhandled. Not found on any medium.
2473 err("[USD] Free Space Table is unhandled. Skipping.\n");
2474 }
2475 if(phd->freedSpaceBitmap.extLength > 0) {
2476 //Unhandled. Not found on any medium.
2477 err("[USD] Unallocated Space Table is unhandled. Skipping.\n");
2478 }
2479
2480 if(phd->unallocSpaceBitmap.extLength > 3) { //0,1,2,3 are special values ECMA 167r3 4/14.14.1.1
2481 uint32_t lsnBase = disc->udf_pd[vds]->partitionStartingLocation;
2482 struct spaceBitmapDesc *sbd = (struct spaceBitmapDesc *)(dev + (lsnBase + phd->unallocSpaceBitmap.extPosition)*sectorsize);
2483 if(sbd->descTag.tagIdent != TAG_IDENT_SBD) {
2484 err("SBD not found\n");
2485 return -1;
2486 }
2487 dbg("[SBD] NumOfBits: %d\n", sbd->numOfBits);
2488 dbg("[SBD] NumOfBytes: %d\n", sbd->numOfBytes);
2489
2490 dbg("Bitmap: %d, %p\n", (lsnBase + phd->unallocSpaceBitmap.extPosition), sbd->bitmap);
2491 memcpy(sbd->bitmap, stats->actPartitionBitmap, sbd->numOfBytes);
2492 dbg("MEMCPY DONE\n");
2493
2494 //Recalculate CRC and checksum
2495 sbd->descTag.descCRC = calculate_crc(sbd, sbd->descTag.descCRCLength + sizeof(tag));
2496 sbd->descTag.tagChecksum = calculate_checksum(sbd->descTag);
2497 imp("PD SBD recovery was successful.\n");
2498 return 0;
2499 }
2500 err("PD SBD recovery failed.\n");
2501 return 1;
2502 }
2503
2520 int get_pd(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, struct filesystemStats *stats, vds_sequence_t *seq) {
2521 int vds = -1;
2522 if((vds=get_correct(seq, TAG_IDENT_PD)) < 0) {
2523 err("No correct PD found. Aborting.\n");
2524 return 4;
2525 }
2526 struct partitionHeaderDesc *phd = (struct partitionHeaderDesc *)(disc->udf_pd[vds]->partitionContentsUse);
2527 dbg("[USD] UST pos: %d, len: %d\n", phd->unallocSpaceTable.extPosition, phd->unallocSpaceTable.extLength);
2528 dbg("[USD] USB pos: %d, len: %d\n", phd->unallocSpaceBitmap.extPosition, phd->unallocSpaceBitmap.extLength);
2529 dbg("[USD] FST pos: %d, len: %d\n", phd->freedSpaceTable.extPosition, phd->freedSpaceTable.extLength);
2530 dbg("[USD] FSB pos: %d, len: %d\n", phd->freedSpaceBitmap.extPosition, phd->freedSpaceBitmap.extLength);
2531
2532 if(phd->unallocSpaceTable.extLength > 0) {
2533 //Unhandled. Not found on any medium.
2534 err("[USD] Unallocated Space Table is unhandled. Skipping.\n");
2535 return -128;
2536 }
2537 if(phd->freedSpaceTable.extLength > 0) {
2538 //Unhandled. Not found on any medium.
2539 err("[USD] Free Space Table is unhandled. Skipping.\n");
2540 return -128;
2541 }
2542 if(phd->freedSpaceBitmap.extLength > 0) {
2543 //Unhandled. Not found on any medium.
2544 err("[USD] Freed Space Bitmap is unhandled. Skipping.\n");
2545 return -128;
2546 }
2547 if(phd->unallocSpaceBitmap.extLength > 3) { //0,1,2,3 are special values ECMA 167r3 4/14.14.1.1
2548 uint32_t lsnBase = disc->udf_pd[vds]->partitionStartingLocation;
2549 dbg("LSNBase: %d\n", lsnBase);
2550 struct spaceBitmapDesc *sbd = (struct spaceBitmapDesc *)(dev + (lsnBase + phd->unallocSpaceBitmap.extPosition)*sectorsize);
2551 if(sbd->descTag.tagIdent != TAG_IDENT_SBD) {
2552 err("SBD not found\n");
2553 return -1;
2554 }
2555 if(!checksum(sbd->descTag)) {
2556 err("SBD checksum error. Continue with caution.\n");
2557 seq->pd.error |= E_CHECKSUM;
2558 }
2559 if(crc(sbd, sbd->descTag.descCRCLength + sizeof(tag))) {
2560 err("SBD CRC error. Continue with caution.\n");
2561 seq->pd.error |= E_CRC;
2562 }
2563 dbg("SBD is ok\n");
2564 dbg("[SBD] NumOfBits: %d\n", sbd->numOfBits);
2565 dbg("[SBD] NumOfBytes: %d\n", sbd->numOfBytes);
2566 dbg("Bitmap: %d, %p\n", (lsnBase + phd->unallocSpaceBitmap.extPosition), sbd->bitmap);
2567
2568 //Create array for used/unused blocks counting
2569 stats->actPartitionBitmap = calloc(sbd->numOfBytes, 1);
2570 memset(stats->actPartitionBitmap, 0xff, sbd->numOfBytes);
2571 stats->partitionNumOfBytes = sbd->numOfBytes;
2572 stats->partitionNumOfBits = sbd->numOfBits;
2573
2574 //Get actual bitmap statistics
2575 uint32_t usedBlocks = 0;
2576 uint32_t unusedBlocks = 0;
2577 uint8_t count = 0;
2578 uint8_t v = 0;
2579 for(int i=0; i<sbd->numOfBytes-1; i++) {
2580 v = sbd->bitmap[i];
2581 count = BitsSetTable256[v & 0xff] + BitsSetTable256[(v >> 8) & 0xff] + BitsSetTable256[(v >> 16) & 0xff] + BitsSetTable256[v >> 24];
2582 usedBlocks += 8-count;
2583 unusedBlocks += count;
2584 }
2585 dbg("Unused blocks: %d\n", unusedBlocks);
2586 dbg("Used Blocks: %d\n", usedBlocks);
2587
2588 uint8_t bitCorrection = sbd->numOfBytes*8-sbd->numOfBits;
2589 dbg("BitCorrection: %d\n", bitCorrection);
2590 v = sbd->bitmap[sbd->numOfBytes-1];
2591 dbg("Bitmap last: 0x%02x\n", v);
2592 for(int i=0; i<8 - bitCorrection; i++) {
2593 dbg("Mask: 0x%02x, Result: 0x%02x\n", (1 << i), v & (1 << i));
2594 if(v & (1 << i))
2595 unusedBlocks++;
2596 else
2597 usedBlocks++;
2598 }
2599
2600
2601 stats->expUsedBlocks = usedBlocks;
2602 stats->expUnusedBlocks = unusedBlocks;
2603 stats->expPartitionBitmap = sbd->bitmap;
2604 dbg("Unused blocks: %d\n", unusedBlocks);
2605 dbg("Used Blocks: %d\n", usedBlocks);
2606 }
2607
2608 //Mark used space
2609 increment_used_space(stats, phd->unallocSpaceTable.extLength, phd->unallocSpaceTable.extPosition);
2610 increment_used_space(stats, phd->unallocSpaceBitmap.extLength, phd->unallocSpaceBitmap.extPosition);
2611 increment_used_space(stats, phd->freedSpaceTable.extLength, phd->freedSpaceTable.extPosition);
2612 increment_used_space(stats, phd->freedSpaceBitmap.extLength, phd->freedSpaceBitmap.extPosition);
2613
2614 return 0;
2615 }
2616
2633 int fix_lvid(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, struct filesystemStats *stats, vds_sequence_t *seq) {
2634 int vds = -1;
2635 if((vds=get_correct(seq, TAG_IDENT_LVD)) < 0) {
2636 err("No correct LVD found. Aborting.\n");
2637 return 4;
2638 }
2639
2640 uint32_t loc = disc->udf_lvd[vds]->integritySeqExt.extLocation;
2641 uint32_t len = disc->udf_lvd[vds]->integritySeqExt.extLength;
2642 uint16_t size = sizeof(struct logicalVolIntegrityDesc) + disc->udf_lvid->numOfPartitions*4*2 + disc->udf_lvid->lengthOfImpUse;
2643 dbg("LVID: loc: %d, len: %d, size: %d\n", loc, len, size);
2644
2645 struct logicalVolIntegrityDesc *lvid = (struct logicalVolIntegrityDesc *)(dev+loc*sectorsize);
2646 struct impUseLVID *impUse = (struct impUseLVID *)((uint8_t *)(disc->udf_lvid) + sizeof(struct logicalVolIntegrityDesc) + 8*disc->udf_lvid->numOfPartitions); //this is because of ECMA 167r3, 3/24, fig 22
2647
2648 // Fix PD too
2649 fix_pd(dev, disc, sectorsize, stats, seq);
2650
2651 // Fix files/dir amounts
2652 impUse->numOfFiles = stats->countNumOfFiles;
2653 impUse->numOfDirs = stats->countNumOfDirs;
2654
2655 // Fix Next Unique ID by maximal found +1
2656 ((struct logicalVolHeaderDesc *)(disc->udf_lvid->logicalVolContentsUse))->uniqueID = stats->maxUUID+1;
2657
2658 // Set recording date and time to now.
2659 time_t t = time(NULL);
2660 struct tm tmlocal = *localtime(&t);
2661 struct tm tm = *gmtime(&t);
2662 int8_t hrso = tmlocal.tm_hour - tm.tm_hour;
2663 if(hrso > 12 || hrso < -12) {
2664 hrso += 24;
2665 }
2666
2667 int8_t mino = tmlocal.tm_min - tm.tm_min;
2668 int16_t offset = hrso*60+mino;
2669 dbg("Offset: %d, hrs: %d, min: %d\n", offset, hrso, mino);
2670 dbg("lhr: %d, hr: %d\n", tmlocal.tm_hour, tm.tm_hour);
2671 timestamp *ts = &(disc->udf_lvid->recordingDateAndTime);
2672 ts->typeAndTimezone = (1 << 12) | (offset >= 0 ? offset : (0x1000-offset));
2673 ts->year = tmlocal.tm_year + 1900;
2674 ts->month = tmlocal.tm_mon + 1;
2675 ts->day = tmlocal.tm_mday;
2676 ts->hour = tmlocal.tm_hour;
2677 ts->minute = tmlocal.tm_min;
2678 ts->second = tmlocal.tm_sec;
2679 ts->centiseconds = 0;
2680 ts->hundredsOfMicroseconds = 0;
2681 ts->microseconds = 0;
2682 dbg("Type and Timezone: 0x%04x\n", ts->typeAndTimezone);
2683
2684 uint32_t newFreeSpace = disc->udf_lvid->freeSpaceTable[1] - stats->usedSpace/sectorsize;
2685 disc->udf_lvid->freeSpaceTable[0] = cpu_to_le32(newFreeSpace);
2686 dbg("New Free Space: %d\n", disc->udf_lvid->freeSpaceTable[0]);
2687
2688 // Close integrity (last thing before write)
2689 disc->udf_lvid->integrityType = LVID_INTEGRITY_TYPE_CLOSE;
2690
2691 //Recalculate CRC and checksum
2692 disc->udf_lvid->descTag.descCRC = calculate_crc(disc->udf_lvid, size);
2693 disc->udf_lvid->descTag.tagChecksum = calculate_checksum(disc->udf_lvid->descTag);
2694 //Write changes back to medium
2695 memcpy(lvid, disc->udf_lvid, size);
2696
2697 imp("LVID recovery was successful.\n");
2698 return 0;
2699 }
2700
fix_lvid
int fix_lvid(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, struct filesystemStats *stats, vds_sequence_t *seq)
Fix LVID values.
Definition: udffsck.c:2633
FID_FILE_CHAR_METADATA
#define FID_FILE_CHAR_METADATA
Definition: ecma_167.h:478
avdp_type_e
avdp_type_e
Definition: udffsck.h:39
allocDescs
extent_ad allocDescs[0]
Definition: ecma_167.h:67
filesystemStats::minUDFWriteRev
uint16_t minUDFWriteRev
Definition: udffsck.h:80
filesystemStats::partitionSizeBlocks
uint32_t partitionSizeBlocks
Definition: udffsck.h:85
verify_vds
int verify_vds(struct udf_disc *disc, vds_type_e vds, vds_sequence_t *seq)
VDS verification structure.
Definition: udffsck.c:2066
impUseExtAttr::impIdent
regid impIdent
Definition: ecma_167.h:714
MAX_DEPTH
#define MAX_DEPTH
Maximal printed filetree depth is MAX_DEPTH/4. Required by function depth2str().
Definition: udffsck.c:45
TAG_IDENT_PVD
#define TAG_IDENT_PVD
Definition: ecma_167.h:182
primaryVolDesc::predecessorVolDescSeqLocation
uint32_t predecessorVolDescSeqLocation
Definition: ecma_167.h:224
fileSetDesc::rootDirectoryICB
long_ad rootDirectoryICB
Definition: ecma_167.h:441
ICBTAG_FLAG_AD_EXTENDED
#define ICBTAG_FLAG_AD_EXTENDED
Definition: ecma_167.h:528
FE_PERM_G_CHATTR
#define FE_PERM_G_CHATTR
Definition: ecma_167.h:593
appUseExtAttr
Definition: ecma_167.h:719
fileEntry::lengthExtendedAttr
uint32_t lengthExtendedAttr
Definition: ecma_167.h:578
translate_fid
uint8_t translate_fid(const uint8_t *dev, const struct udf_disc *disc, uint32_t lbnlsn, uint32_t lsn, uint8_t *allocDescs, uint32_t lengthAllocDescs, uint16_t icb_ad, struct filesystemStats *stats, uint32_t depth, vds_sequence_t *seq, uint8_t *status)
FID allocation descriptor position translation function.
Definition: udffsck.c:1074
filesystemStats
Definition: udffsck.h:71
partitionDesc::partitionContentsUse
uint8_t partitionContentsUse[128]
Definition: ecma_167.h:267
logicalVolDesc::integritySeqExt
extent_ad integritySeqExt
Definition: ecma_167.h:309
ICBTAG_FILE_TYPE_IE
#define ICBTAG_FILE_TYPE_IE
Definition: ecma_167.h:512
filesystemStats::blocksize
uint16_t blocksize
Definition: udffsck.h:72
cpu_to_le32
#define cpu_to_le32(x)
Definition: bswap.h:247
crc
int crc(void *restrict desc, uint16_t size)
Wrapper function for CRC calculation.
Definition: udffsck.c:134
impUseLVID
Definition: udffsck.h:108
extendedFileEntry
Definition: ecma_167.h:798
vds_sequence_t
Definition: udffsck.h:56
fileInfo::filename
char * filename
Definition: udffsck.h:98
line
char line[256]
Definition: wrudf.c:27
VSD_STD_ID_NSR03
#define VSD_STD_ID_NSR03
Definition: ecma_167.h:118
descTag
tag descTag
Definition: ecma_167.h:64
udf_disc::udf_lvid
struct logicalVolIntegrityDesc * udf_lvid
Definition: libudffs.h:118
fileEntry::icbTag
icbtag icbTag
Definition: ecma_167.h:561
terminatingExtendedAreaDesc::structVersion
uint8_t structVersion
Definition: ecma_167.h:135
logicalVolDesc::logicalBlockSize
uint32_t logicalBlockSize
Definition: ecma_167.h:302
FE_PERM_G_DELETE
#define FE_PERM_G_DELETE
Definition: ecma_167.h:594
ICBTAG_FILE_TYPE_PIE
#define ICBTAG_FILE_TYPE_PIE
Definition: ecma_167.h:511
fix_avdp
int fix_avdp(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, size_t devsize, avdp_type_e target)
Fix target AVDP's extent length.
Definition: udffsck.c:2271
anchorVolDescPtr::descTag
tag descTag
Definition: ecma_167.h:235
impUseLVID::numOfDirs
uint32_t numOfDirs
Definition: udffsck.h:111
udf_disc::udf_pd
struct partitionDesc * udf_pd[2]
Definition: libudffs.h:114
logicalVolIntegrityDesc::logicalVolContentsUse
uint8_t logicalVolContentsUse[32]
Definition: ecma_167.h:366
terminatingExtendedAreaDesc::stdIdent
uint8_t stdIdent[VSD_STD_ID_LEN]
Definition: ecma_167.h:134
blank
int blank(int fd, int type, int start)
Definition: ide-pc.c:77
get_vds
int get_vds(uint8_t *dev, struct udf_disc *disc, int sectorsize, avdp_type_e avdp, vds_type_e vds, vds_sequence_t *seq)
Loads Volume Descriptor Sequence (VDS) and stores it at struct udf_disc.
Definition: udffsck.c:576
impUseExtAttr::impUseLength
uint32_t impUseLength
Definition: ecma_167.h:713
terminatingExtendedAreaDesc::structType
uint8_t structType
Definition: ecma_167.h:133
metadata_t::tagLocation
uint32_t tagLocation
descriptor declared position
Definition: udffsck.h:52
calculate_crc
uint16_t calculate_crc(void *restrict desc, uint16_t size)
CRC calcultaion wrapper for udf_crc() function from libudffs.
Definition: udffsck.c:114
ICBTAG_FILE_TYPE_USE
#define ICBTAG_FILE_TYPE_USE
Definition: ecma_167.h:510
FID_FILE_CHAR_PARENT
#define FID_FILE_CHAR_PARENT
Definition: ecma_167.h:477
unallocSpaceDesc::descTag
tag descTag
Definition: ecma_167.h:346
fileSetDesc::fileSetIdent
dstring fileSetIdent[32]
Definition: ecma_167.h:438
write_avdp
int write_avdp(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, size_t devsize, avdp_type_e source, avdp_type_e target)
Writes back specified AVDP from udf_disc structure to device.
Definition: udffsck.c:2200
partitionDesc::partitionNumber
uint16_t partitionNumber
Definition: ecma_167.h:265
fileEntry::logicalBlocksRecorded
uint64_t logicalBlocksRecorded
Definition: ecma_167.h:570
TAG_IDENT_EAHD
#define TAG_IDENT_EAHD
Definition: ecma_167.h:418
anchorVolDescPtr
Definition: ecma_167.h:233
get_file
uint8_t get_file(const uint8_t *dev, const struct udf_disc *disc, uint32_t lbnlsn, uint32_t lsn, struct filesystemStats *stats, uint32_t depth, uint32_t uuid, struct fileInfo info, vds_sequence_t *seq)
(E)FE parsing function
Definition: udffsck.c:1557
padding
uint8_t padding[0]
Definition: ecma_167.h:72
partitionDesc::partitionStartingLocation
uint32_t partitionStartingLocation
Definition: ecma_167.h:269
unallocSpaceDesc::numAllocDescs
uint32_t numAllocDescs
Definition: ecma_167.h:348
EXTATTR_APP_USE
#define EXTATTR_APP_USE
Definition: ecma_167.h:736
get_tag_location
uint32_t get_tag_location(vds_sequence_t *seq, uint16_t tagIdent, vds_type_e vds)
Support function for getting tag location from seq structure.
Definition: udffsck.c:2040
E_CHECKSUM
#define E_CHECKSUM
Definition: udffsck.h:118
filesystemStats::usedSpace
uint64_t usedSpace
Definition: udffsck.h:83
udf_crc
uint16_t udf_crc(uint8_t *, uint32_t, uint16_t)
Definition: crc.c:88
ICBTAG_FLAG_AD_MASK
#define ICBTAG_FLAG_AD_MASK
Definition: ecma_167.h:525
fix_vds
int fix_vds(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, avdp_type_e source, vds_sequence_t *seq)
Fix VDS sequence.
Definition: udffsck.c:2362
vds_type_e
vds_type_e
Definition: udffsck.h:45
fix_pd
int fix_pd(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, struct filesystemStats *stats, vds_sequence_t *seq)
Fix PD Partition Header contents.
Definition: udffsck.c:2455
RESERVE_VDS
Definition: udffsck.h:47
impUseLVID::numOfFiles
uint32_t numOfFiles
Definition: udffsck.h:110
FE_PERM_O_CHATTR
#define FE_PERM_O_CHATTR
Definition: ecma_167.h:588
FE_PERM_G_EXEC
#define FE_PERM_G_EXEC
Definition: ecma_167.h:590
E_POSITION
#define E_POSITION
Definition: udffsck.h:120
logicalVolDesc::mapTableLength
uint32_t mapTableLength
Definition: ecma_167.h:305
TAG_IDENT_TD
#define TAG_IDENT_TD
Definition: ecma_167.h:189
prompt
int prompt(const char *format,...)
Simple prompt printing out message and accepting y/Y/n/N. Anything else restarts prompt.
Definition: utils.c:184
E_UUID
#define E_UUID
Definition: udffsck.h:122
fileEntry::permissions
uint32_t permissions
Definition: ecma_167.h:564
extendedAttrHeaderDesc::impAttrLocation
uint32_t impAttrLocation
Definition: ecma_167.h:625
decode_utf8
size_t decode_utf8(dstring *, char *, size_t)
Definition: unicode.c:32
TAG_IDENT_AED
#define TAG_IDENT_AED
Definition: ecma_167.h:414
FE_PERM_G_WRITE
#define FE_PERM_G_WRITE
Definition: ecma_167.h:591
udf_disc::udf_pvd
struct primaryVolDesc * udf_pvd[2]
Definition: libudffs.h:112
get_pd
int get_pd(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, struct filesystemStats *stats, vds_sequence_t *seq)
Get PD Partition Header contents.
Definition: udffsck.c:2520
timestamp2epoch
time_t timestamp2epoch(timestamp t)
UDF timestamp to Unix timestamp conversion function.
Definition: udffsck.c:196
markUsedBlock
uint8_t markUsedBlock(struct filesystemStats *stats, uint32_t lbn, uint32_t size, uint8_t mark)
Marks used blocks in actual bitmap.
Definition: udffsck.c:843
inspect_fid
uint8_t inspect_fid(const uint8_t *dev, const struct udf_disc *disc, uint32_t lbnlsn, uint32_t lsn, uint8_t *base, uint32_t *pos, struct filesystemStats *stats, uint32_t depth, vds_sequence_t *seq, uint8_t *status)
FID parsing function.
Definition: udffsck.c:1315
lengthAllocDescs
uint32_t lengthAllocDescs
Definition: ecma_167.h:66
primaryVolDesc::volDescSeqNum
uint32_t volDescSeqNum
Definition: ecma_167.h:206
udf_disc::udf_anchor
struct anchorVolDescPtr * udf_anchor[3]
Definition: libudffs.h:111
impUseLVID::minUDFWriteRev
uint16_t minUDFWriteRev
Definition: udffsck.h:113
print_file_info
void print_file_info(struct fileInfo info, uint32_t depth)
File information printing function.
Definition: udffsck.c:256
FE_PERM_U_DELETE
#define FE_PERM_U_DELETE
Definition: ecma_167.h:599
depth2str
char * depth2str(uint32_t depth)
File tree prefix creator.
Definition: udffsck.c:55
note
void note(const char *format,...)
Note output.
Definition: utils.c:328
autofix
int autofix
Definition: options.c:34
spaceBitmapDesc::descTag
tag descTag
Definition: ecma_167.h:751
uniqueID
uint64_t uniqueID
Definition: ecma_167.h:81
logicalVolDesc::descTag
tag descTag
Definition: ecma_167.h:298
genericFormat::attrLength
uint32_t attrLength
Definition: ecma_167.h:635
MARK_BLOCK
#define MARK_BLOCK
Mark switch for markUsedBlock() function.
Definition: udffsck.c:42
filesystemStats::countNumOfDirs
uint32_t countNumOfDirs
Definition: udffsck.h:78
partitionDesc::descTag
tag descTag
Definition: ecma_167.h:262
logicalVolIntegrityDesc::freeSpaceTable
uint32_t freeSpaceTable[0]
Definition: ecma_167.h:369
FE_PERM_U_READ
#define FE_PERM_U_READ
Definition: ecma_167.h:597
filesystemStats::partitionNumOfBytes
uint32_t partitionNumOfBytes
Definition: udffsck.h:88
E_TIMESTAMP
#define E_TIMESTAMP
Definition: udffsck.h:123
fileSetDesc::logicalVolIdent
dstring logicalVolIdent[128]
Definition: ecma_167.h:436
TAG_IDENT_SBD
#define TAG_IDENT_SBD
Definition: ecma_167.h:420
utils.h
dbg
void dbg(const char *format,...)
Debug output.
Definition: utils.c:296
extendedFileEntry::lengthAllocDescs
uint32_t lengthAllocDescs
Definition: ecma_167.h:823
fileEntry::fileLinkCount
uint16_t fileLinkCount
Definition: ecma_167.h:565
get_correct
int get_correct(vds_sequence_t *seq, uint16_t tagIdent)
Selects MAIN_VDS or RESERVE_VDS for required descriptor based on errors.
Definition: udffsck.c:709
filesystemStats::AVDPSerialNum
uint16_t AVDPSerialNum
Definition: udffsck.h:82
filesystemStats::actUUID
uint64_t actUUID
Definition: udffsck.h:73
primaryVolDesc::descTag
tag descTag
Definition: ecma_167.h:205
TAG_IDENT_FE
#define TAG_IDENT_FE
Definition: ecma_167.h:417
increment_used_space
void increment_used_space(struct filesystemStats *stats, uint64_t increment, uint32_t position)
Pair function capturing used space and its position.
Definition: udffsck.c:1503
FIRST_AVDP
Definition: udffsck.h:40
TAG_IDENT_IUVD
#define TAG_IDENT_IUVD
Definition: ecma_167.h:185
decrement_used_space
void decrement_used_space(struct filesystemStats *stats, uint64_t increment, uint32_t position)
Pair function capturing used space and its position.
Definition: udffsck.c:1523
ICBTAG_FILE_TYPE_BLOCK
#define ICBTAG_FILE_TYPE_BLOCK
Definition: ecma_167.h:515
FID_FILE_CHAR_DIRECTORY
#define FID_FILE_CHAR_DIRECTORY
Definition: ecma_167.h:475
is_udf
int is_udf(uint8_t *dev, int *sectorsize, int force_sectorsize)
UDF VRS detection function.
Definition: udffsck.c:347
fileInfo::modTime
timestamp modTime
Definition: udffsck.h:104
TAG_IDENT_PD
#define TAG_IDENT_PD
Definition: ecma_167.h:186
logicalVolDesc
Definition: ecma_167.h:296
partitionHeaderDesc
Definition: ecma_167.h:449
VDS_STRUCT_AMOUNT
#define VDS_STRUCT_AMOUNT
Maximum amount of VDS descriptors.
Definition: udffsck.h:36
ICBTAG_FLAG_AD_SHORT
#define ICBTAG_FLAG_AD_SHORT
Definition: ecma_167.h:526
E_WRONGDESC
#define E_WRONGDESC
Definition: udffsck.h:121
fileSetDesc::descTag
tag descTag
Definition: ecma_167.h:427
primaryVolDesc
Definition: ecma_167.h:203
get_file_structure
uint8_t get_file_structure(const uint8_t *dev, const struct udf_disc *disc, uint32_t lbnlsn, struct filesystemStats *stats, vds_sequence_t *seq)
File tree entry point.
Definition: udffsck.c:1953
lvid
struct logicalVolIntegrityDesc * lvid
Definition: wrudf.c:71
primaryVolDesc::volSetIdent
dstring volSetIdent[128]
Definition: ecma_167.h:215
MAIN_VDS
Definition: udffsck.h:46
udf_disc::udf_usd
struct unallocSpaceDesc * udf_usd[2]
Definition: libudffs.h:115
filesystemStats::actPartitionBitmap
uint8_t * actPartitionBitmap
Definition: udffsck.h:90
partitionHeaderDesc::freedSpaceBitmap
short_ad freedSpaceBitmap
Definition: ecma_167.h:455
options.h
FE_PERM_U_CHATTR
#define FE_PERM_U_CHATTR
Definition: ecma_167.h:598
ICBTAG_FLAG_AD_LONG
#define ICBTAG_FLAG_AD_LONG
Definition: ecma_167.h:527
fileIdentDesc::fileVersionNum
uint16_t fileVersionNum
Definition: ecma_167.h:463
get_volume_identifier
int get_volume_identifier(struct udf_disc *disc, struct filesystemStats *stats, vds_sequence_t *seq)
Select various volume identifiers and store them at stats structure.
Definition: udffsck.c:818
FE_PERM_O_READ
#define FE_PERM_O_READ
Definition: ecma_167.h:587
volStructDesc::stdIdent
uint8_t stdIdent[VSD_STD_ID_LEN]
Definition: ecma_167.h:104
filesystemStats::countNumOfFiles
uint32_t countNumOfFiles
Definition: udffsck.h:76
FE_PERM_G_READ
#define FE_PERM_G_READ
Definition: ecma_167.h:592
impUseLVID::minUDFReadRev
uint16_t minUDFReadRev
Definition: udffsck.h:112
TAG_IDENT_FSD
#define TAG_IDENT_FSD
Definition: ecma_167.h:412
vds_sequence_t::lvid
metadata_t lvid
Definition: udffsck.h:60
VSD_STD_ID_CDW02
#define VSD_STD_ID_CDW02
Definition: ecma_167.h:117
logicalVolIntegrityDesc::nextIntegrityExt
extent_ad nextIntegrityExt
Definition: ecma_167.h:365
calculate_checksum
uint8_t calculate_checksum(tag descTag)
Checksum calculation function for tags.
Definition: udffsck.c:82
filesystemStats::expNumOfDirs
uint32_t expNumOfDirs
Definition: udffsck.h:77
fileIdentDesc::fileCharacteristics
uint8_t fileCharacteristics
Definition: ecma_167.h:464
beginningExtendedAreaDesc
Definition: ecma_167.h:122
copy_descriptor
int copy_descriptor(uint8_t *dev, struct udf_disc *disc, size_t sectorsize, uint32_t sourcePosition, uint32_t destinationPosition, size_t size)
Copy descriptor from one position to another on medium.
Definition: udffsck.c:2162
TAG_IDENT_LVD
#define TAG_IDENT_LVD
Definition: ecma_167.h:187
filesystemStats::LVIDtimestamp
timestamp LVIDtimestamp
Definition: udffsck.h:92
filesystemStats::volumeSetIdent
dstring * volumeSetIdent
Definition: udffsck.h:94
filesystemStats::maxUUID
uint64_t maxUUID
Definition: udffsck.h:74
UNMARK_BLOCK
#define UNMARK_BLOCK
Unmark switch for markUsedBlock() function.
Definition: udffsck.c:43
fileIdentDesc::lengthOfImpUse
uint16_t lengthOfImpUse
Definition: ecma_167.h:467
fileInfo::fileCharacteristics
uint8_t fileCharacteristics
Definition: udffsck.h:99
allocExtDesc::lengthAllocDescs
uint32_t lengthAllocDescs
Definition: ecma_167.h:485
vds_sequence_t::pd
metadata_t pd
Definition: udffsck.h:61
ICBTAG_FILE_TYPE_REGULAR
#define ICBTAG_FILE_TYPE_REGULAR
Definition: ecma_167.h:514
usd
struct unallocSpaceDesc * usd
Definition: wrudf.c:69
filesystemStats::expPartitionBitmap
uint8_t * expPartitionBitmap
Definition: udffsck.h:91
fileEntry
Definition: ecma_167.h:558
checksum
int checksum(tag descTag)
Wrapper function for checksum.
Definition: udffsck.c:101
VSD_STD_ID_NSR01
#define VSD_STD_ID_NSR01
Definition: ecma_167.h:111
ICBTAG_FILE_TYPE_STREAMDIR
#define ICBTAG_FILE_TYPE_STREAMDIR
Definition: ecma_167.h:522
primaryVolDesc::primaryVolDescNum
uint32_t primaryVolDescNum
Definition: ecma_167.h:207
BitsSetTable256
static const unsigned char BitsSetTable256[256]
Support array for bit counting.
Definition: udffsck.c:2431
beginningExtendedAreaDesc::structType
uint8_t structType
Definition: ecma_167.h:124
fileSetDesc
Definition: ecma_167.h:425
VSD_STD_ID_BEA01
#define VSD_STD_ID_BEA01
Definition: ecma_167.h:114
TAG_IDENT_LVID
#define TAG_IDENT_LVID
Definition: ecma_167.h:190
extendedFileEntry::logicalBlocksRecorded
uint64_t logicalBlocksRecorded
Definition: ecma_167.h:811
impUse
uint8_t impUse[64]
Definition: ecma_167.h:82
print_file_chunks
void print_file_chunks(struct filesystemStats *stats)
fileEntry::informationLength
uint64_t informationLength
Definition: ecma_167.h:569
logicalVolIntegrityDesc::descTag
tag descTag
Definition: ecma_167.h:362
partitionHeaderDesc::unallocSpaceBitmap
short_ad unallocSpaceBitmap
Definition: ecma_167.h:452
error
Definition: utils.c:44
metadata_t::error
uint8_t error
errors found on descriptor
Definition: udffsck.h:53
msg
void msg(const char *format,...)
Message output.
Definition: utils.c:344
logicalVolHeaderDesc
Definition: ecma_167.h:782
extendedFileEntry::allocDescs
uint8_t allocDescs[0]
Definition: ecma_167.h:825
allocExtDesc::descTag
tag descTag
Definition: ecma_167.h:483
fileEntry::lengthAllocDescs
uint32_t lengthAllocDescs
Definition: ecma_167.h:579
impUseExtAttr
Definition: ecma_167.h:707
partitionDesc::partitionLength
uint32_t partitionLength
Definition: ecma_167.h:270
vds_sequence_t::reserve
metadata_t reserve[VDS_STRUCT_AMOUNT]
Definition: udffsck.h:59
filesystemStats::partitionNumOfBits
uint32_t partitionNumOfBits
Definition: udffsck.h:89
beginningExtendedAreaDesc::stdIdent
uint8_t stdIdent[VSD_STD_ID_LEN]
Definition: ecma_167.h:125
fileEntry::descTag
tag descTag
Definition: ecma_167.h:560
VSD_STD_ID_TEA01
#define VSD_STD_ID_TEA01
Definition: ecma_167.h:119
udf_disc::udf_td
struct terminatingDesc * udf_td[2]
Definition: libudffs.h:117
logicalVolDesc::numPartitionMaps
uint32_t numPartitionMaps
Definition: ecma_167.h:306
impUseLVID::maxUDFWriteRev
uint16_t maxUDFWriteRev
Definition: udffsck.h:114
get_avdp
int get_avdp(uint8_t *dev, struct udf_disc *disc, int *sectorsize, size_t devsize, avdp_type_e type, int force_sectorsize, struct filesystemStats *stats)
Locate AVDP on device and store it.
Definition: udffsck.c:469
fileIdentDesc::lengthFileIdent
uint8_t lengthFileIdent
Definition: ecma_167.h:465
udffsck.h
fileSetDesc::streamDirectoryICB
long_ad streamDirectoryICB
Definition: ecma_167.h:444
filesystemStats::expNumOfFiles
uint32_t expNumOfFiles
Definition: udffsck.h:75
VSD_STD_ID_NSR02
#define VSD_STD_ID_NSR02
Definition: ecma_167.h:110
fileInfo::size
uint64_t size
Definition: udffsck.h:102
FE_PERM_O_WRITE
#define FE_PERM_O_WRITE
Definition: ecma_167.h:586
extendedFileEntry::modificationTime
timestamp modificationTime
Definition: ecma_167.h:813
logicalVolIntegrityDesc
Definition: ecma_167.h:360
terminatingDesc
Definition: ecma_167.h:353
check_position
int check_position(tag descTag, uint32_t position)
Position check function.
Definition: udffsck.c:150
udf_disc
Definition: libudffs.h:95
FE_PERM_U_WRITE
#define FE_PERM_U_WRITE
Definition: ecma_167.h:596
VSD_STD_ID_BOOT2
#define VSD_STD_ID_BOOT2
Definition: ecma_167.h:115
primaryVolDesc::volSeqNum
uint16_t volSeqNum
Definition: ecma_167.h:209
volStructDesc
Definition: ecma_167.h:101
ICBTAG_FILE_TYPE_SOCKET
#define ICBTAG_FILE_TYPE_SOCKET
Definition: ecma_167.h:519
fileEntry::modificationTime
timestamp modificationTime
Definition: ecma_167.h:572
append_error
int append_error(vds_sequence_t *seq, uint16_t tagIdent, vds_type_e vds, uint8_t error)
Support function for appending error to seq structure.
Definition: udffsck.c:2014
FE_PERM_U_EXEC
#define FE_PERM_U_EXEC
Definition: ecma_167.h:595
impUseVolDesc::descTag
tag descTag
Definition: ecma_167.h:253
fileEntry::uniqueID
uint64_t uniqueID
Definition: ecma_167.h:577
partitionHeaderDesc::freedSpaceTable
short_ad freedSpaceTable
Definition: ecma_167.h:454
volStructDesc::structVersion
uint8_t structVersion
Definition: ecma_167.h:105
vds_sequence_t::main
metadata_t main[VDS_STRUCT_AMOUNT]
Definition: udffsck.h:58
descriptor_name
char * descriptor_name(uint16_t descIdent)
Get descriptor name string.
Definition: udffsck.c:2326
logicalVolIntegrityDesc::recordingDateAndTime
timestamp recordingDateAndTime
Definition: ecma_167.h:363
logicalVolIntegrityDesc::numOfPartitions
uint32_t numOfPartitions
Definition: ecma_167.h:367
anchorVolDescPtr::mainVolDescSeqExt
extent_ad mainVolDescSeqExt
Definition: ecma_167.h:236
TAG_IDENT_FID
#define TAG_IDENT_FID
Definition: ecma_167.h:413
E_CRC
#define E_CRC
Definition: udffsck.h:119
filesystemStats::freeSpaceBlocks
uint32_t freeSpaceBlocks
Definition: udffsck.h:84
fileEntry::impIdent
regid impIdent
Definition: ecma_167.h:576
VSD_STD_ID_CD001
#define VSD_STD_ID_CD001
Definition: ecma_167.h:116
extendedAttrHeaderDesc
Definition: ecma_167.h:622
filesystemStats::expUnusedBlocks
uint32_t expUnusedBlocks
Definition: udffsck.h:87
logicalVolDesc::partitionMaps
uint8_t partitionMaps[0]
Definition: ecma_167.h:310
extendedFileEntry::descTag
tag descTag
Definition: ecma_167.h:800
FID_FILE_CHAR_DELETED
#define FID_FILE_CHAR_DELETED
Definition: ecma_167.h:476
spaceBitmapDesc::numOfBytes
uint32_t numOfBytes
Definition: ecma_167.h:753
fileIdentDesc::descTag
tag descTag
Definition: ecma_167.h:462
libudffs.h
ICBTAG_FLAG_AD_IN_ICB
#define ICBTAG_FLAG_AD_IN_ICB
Definition: ecma_167.h:529
ICBTAG_FILE_TYPE_EA
#define ICBTAG_FILE_TYPE_EA
Definition: ecma_167.h:517
terminatingExtendedAreaDesc
Definition: ecma_167.h:131
volStructDesc::structType
uint8_t structType
Definition: ecma_167.h:103
ICBTAG_FILE_TYPE_TE
#define ICBTAG_FILE_TYPE_TE
Definition: ecma_167.h:520
err
void err(const char *format,...)
Error output.
Definition: utils.c:392
FE_PERM_O_DELETE
#define FE_PERM_O_DELETE
Definition: ecma_167.h:589
unallocSpaceDesc::volDescSeqNum
uint32_t volDescSeqNum
Definition: ecma_167.h:347
B6
#define B6(n)
FID_FILE_CHAR_HIDDEN
#define FID_FILE_CHAR_HIDDEN
Definition: ecma_167.h:474
logicalVolIntegrityDesc::integrityType
uint32_t integrityType
Definition: ecma_167.h:364
spaceBitmapDesc::numOfBits
uint32_t numOfBits
Definition: ecma_167.h:752
ICBTAG_FILE_TYPE_SYMLINK
#define ICBTAG_FILE_TYPE_SYMLINK
Definition: ecma_167.h:521
extendedAttrHeaderDesc::appAttrLocation
uint32_t appAttrLocation
Definition: ecma_167.h:626
dwarn
void dwarn(const char *format,...)
Debug warning output.
Definition: utils.c:312
fileInfo::fileType
uint8_t fileType
Definition: udffsck.h:100
imp
void imp(const char *format,...)
Important message output.
Definition: utils.c:360
genericFormat::attrType
uint32_t attrType
Definition: ecma_167.h:632
inspect_aed
uint8_t inspect_aed(const uint8_t *dev, uint32_t lsnBase, uint32_t aedlbn, uint32_t *lengthADArray, uint8_t **ADArray, struct filesystemStats *stats, uint8_t *status)
Inspect AED and return array of its allocation descriptors.
Definition: udffsck.c:991
warn
void warn(const char *format,...)
Warning output.
Definition: utils.c:376
logicalVolIntegrityDesc::lengthOfImpUse
uint32_t lengthOfImpUse
Definition: ecma_167.h:368
ICBTAG_FILE_TYPE_DIRECTORY
#define ICBTAG_FILE_TYPE_DIRECTORY
Definition: ecma_167.h:513
filesystemStats::maxUDFWriteRev
uint16_t maxUDFWriteRev
Definition: udffsck.h:81
beginningExtendedAreaDesc::structVersion
uint8_t structVersion
Definition: ecma_167.h:126
print_timestamp
char * print_timestamp(timestamp ts)
Timestamp printing function.
Definition: udffsck.c:170
E_EXTLEN
#define E_EXTLEN
Definition: udffsck.h:126
spaceBitmapDesc::bitmap
uint8_t bitmap[0]
Definition: ecma_167.h:754
genericFormat
Definition: ecma_167.h:630
udf_disc::udf_fsd
struct fileSetDesc * udf_fsd
Definition: libudffs.h:125
filesystemStats::minUDFReadRev
uint16_t minUDFReadRev
Definition: udffsck.h:79
ICBTAG_FILE_TYPE_CHAR
#define ICBTAG_FILE_TYPE_CHAR
Definition: ecma_167.h:516
lvd
struct logicalVolDesc * lvd
Definition: wrudf.c:68
extendedFileEntry::lengthExtendedAttr
uint32_t lengthExtendedAttr
Definition: ecma_167.h:822
allocExtDesc
Definition: ecma_167.h:481
unallocSpaceDesc
Definition: ecma_167.h:344
interactive
int interactive
Definition: options.c:33
count_used_bits
uint64_t count_used_bits(struct filesystemStats *stats)
Counts used bits (blocks) at stats->actParitionBitmap.
Definition: udffsck.c:431
fileInfo::permissions
uint32_t permissions
Definition: udffsck.h:101
get_lvid
int get_lvid(uint8_t *dev, struct udf_disc *disc, int sectorsize, struct filesystemStats *stats, vds_sequence_t *seq)
Loads Logical Volume Integrity Descriptor (LVID) and stores it at struct udf_disc.
Definition: udffsck.c:734
anchorVolDescPtr::reserveVolDescSeqExt
extent_ad reserveVolDescSeqExt
Definition: ecma_167.h:237
extendedFileEntry::uniqueID
uint64_t uniqueID
Definition: ecma_167.h:821
ICBTAG_FILE_TYPE_UNDEF
#define ICBTAG_FILE_TYPE_UNDEF
Definition: ecma_167.h:509
lelb_to_cpu
static lb_addr lelb_to_cpu(lb_addr in)
Definition: udf_endian.h:30
logicalVolDesc::logicalVolContentsUse
uint8_t logicalVolContentsUse[16]
Definition: ecma_167.h:304
compare_timestamps
double compare_timestamps(timestamp a, timestamp b)
UDF Timestamp comparison wrapper.
Definition: udffsck.c:229
fileIdentDesc::fileIdent
uint8_t fileIdent[0]
Definition: ecma_167.h:469
fileIdentDesc
Definition: ecma_167.h:460
partitionDesc
Definition: ecma_167.h:260
metadata_t::tagIdent
uint16_t tagIdent
descriptor identifier
Definition: udffsck.h:51
udf_disc::udf_lvd
struct logicalVolDesc * udf_lvd[2]
Definition: libudffs.h:113
partitionHeaderDesc::unallocSpaceTable
short_ad unallocSpaceTable
Definition: ecma_167.h:451
fatal
void fatal(const char *format,...)
Fatal Error output.
Definition: utils.c:408
spaceBitmapDesc
Definition: ecma_167.h:749
fileEntry::allocDescs
uint8_t allocDescs[0]
Definition: ecma_167.h:581
LVID_INTEGRITY_TYPE_CLOSE
#define LVID_INTEGRITY_TYPE_CLOSE
Definition: ecma_167.h:376
filesystemStats::expUsedBlocks
uint32_t expUsedBlocks
Definition: udffsck.h:86
impUseVolDesc
Definition: ecma_167.h:251
TAG_IDENT_EFE
#define TAG_IDENT_EFE
Definition: ecma_167.h:422
fileInfo
Definition: udffsck.h:97
EXTATTR_IMP_USE
#define EXTATTR_IMP_USE
Definition: ecma_167.h:735
ICBTAG_FILE_TYPE_FIFO
#define ICBTAG_FILE_TYPE_FIFO
Definition: ecma_167.h:518
TAG_IDENT_USD
#define TAG_IDENT_USD
Definition: ecma_167.h:188
fileIdentDesc::icb
long_ad icb
Definition: ecma_167.h:466
udf_disc::udf_iuvd
struct impUseVolDesc * udf_iuvd[2]
Definition: libudffs.h:116
filesystemStats::partitionIdent
dstring * partitionIdent
Definition: udffsck.h:93
TAG_IDENT_AVDP
#define TAG_IDENT_AVDP
Definition: ecma_167.h:183
BLOCK_SIZE
#define BLOCK_SIZE
Minimal VRS search block size.
Definition: udffsck.h:37
FE_PERM_O_EXEC
#define FE_PERM_O_EXEC
Definition: ecma_167.h:585
get_fsd
uint8_t get_fsd(uint8_t *dev, struct udf_disc *disc, int sectorsize, uint32_t *lbnlsn, struct filesystemStats *stats, vds_sequence_t *seq)
Loads File Set Descriptor and stores it at struct udf_disc.
Definition: udffsck.c:923
terminatingDesc::descTag
tag descTag
Definition: ecma_167.h:355