udftools

- Main Page
- Classes
- Files

- File List
- File Members

All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
main.c
Go to the documentation of this file.
1 /*
2 * main.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 #define _POSIX_C_SOURCE 200808L
23
24 #include "config.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/ioctl.h>
31 #include <sys/types.h>
32 #include <sys/file.h>
33 #include <unistd.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <sys/mman.h>
37 #include <limits.h>
38 #include <signal.h>
39
40 #include <ecma_167.h>
41 #include <libudffs.h>
42
43 #include "utils.h"
44 #include "options.h"
45 #include "udffsck.h"
46
47
48 #define PRINT_DISC
49
50 #define MAX_VERSION 0x0201
51
57 void user_interrupt(int dummy) {
58 warn("\nUser interrupted operation. Exiting.\n");
59 exit(32);
60 }
61
68 void segv_interrupt(int dummy) {
69 fatal("Unexpected error, please report it. More info at man page. Exiting.\n");
70 exit(8);
71 }
72
73
74 #define ES_AVDP1 0x0001
75 #define ES_AVDP2 0x0002
76 #define ES_PD 0x0004
77 #define ES_LVID 0x0008
78
96 int main(int argc, char *argv[]) {
97 char *path = NULL;
98 int fd;
99 FILE *fp;
100 int status = 0;
101 int blocksize = -1;
102 struct udf_disc disc = {0};
103 uint8_t *dev;
104 off_t st_size;
105 vds_sequence_t *seq;
106 struct filesystemStats stats = {0};
107 uint16_t error_status = 0;
108 uint16_t fix_status = 0;
109 int force_sectorsize = 0;
110
111 int source = -1;
112
113 signal(SIGINT, user_interrupt);
114 #ifndef DEBUG //if debugging, we want Address Sanitizer to catch those
115 signal(SIGSEGV, segv_interrupt);
116 #endif
117
118 parse_args(argc, argv, &path, &blocksize);
119
120 note("Verbose: %d, Autofix: %d, Interactive: %d\n", verbosity, autofix, interactive);
121
122 if(path == NULL) {
123 err("No medium given. Use -h for help.\n");
124 exit(16);
125 }
126
127 if(blocksize > 0) {
128 force_sectorsize = 1;
129 }
130
131 msg("Medium to analyze: %s\n", path);
132
133 int prot = PROT_READ;
134 int flags = O_RDONLY;
135 // If is there some request for corrections, we need read/write access to medium
136 if(interactive || autofix) {
137 prot |= PROT_WRITE;
138 flags = O_RDWR;
139 dbg("RW\n");
140 }
141
142 if((fd = open(path, flags, 0660)) == -1) {
143 fatal("Error opening %s: %s.", path, strerror(errno));
144 exit(16);
145 }
146 if((fp = fopen(path, "r")) == NULL) {
147 fatal("Error opening %s: %s.", path, strerror(errno));
148 exit(16);
149 }
150 //Lock medium to ensure no-one is going to change during our operation. Make nonblocking, so it will fail when medium is already locked.
151 if(flock(fd, LOCK_EX | LOCK_NB)) {
152 fatal("Error locking %s, %s. Is antoher process using it?\n", path, strerror(errno));
153 exit(16);
154 }
155
156 note("FD: 0x%x\n", fd);
157
158 if(fseeko(fp, 0 , SEEK_END) != 0) {
159 if(errno == EBADF) {
160 err("Medium is not seekable. Aborting.\n");
161 exit(16);
162 } else {
163 err("Unknown seek error (errno: %d). Aborting.\n", errno);
164 exit(16);
165 }
166 }
167 st_size = ftello(fp);
168 dbg("Size: 0x%lx\n", (long)st_size);
169 dev = (uint8_t *)mmap(NULL, st_size, prot, MAP_SHARED, fd, 0);
170 if(dev == MAP_FAILED) {
171 switch(errno) {
172 case EACCES: dbg("EACCES\n"); break;
173 case EAGAIN: dbg("EAGAIN\n"); break;
174 case EBADF: dbg("EBADF\n"); break;
175 case EINVAL: dbg("EINVAL\n"); break;
176 case ENFILE: dbg("ENFILE\n"); break;
177 case ENODEV: dbg("ENODEV\n"); break;
178 case ENOMEM: dbg("ENOMEM\n"); break;
179 case EPERM: dbg("EPERM\n"); break;
180 case ETXTBSY: dbg("ETXTBSY\n"); break;
181 case EOVERFLOW: dbg("EOVERFLOW\n"); break;
182 default: dbg("EUnknown\n"); break;
183 }
184
185
186 fatal("Error maping %s: %s.\n", path, strerror(errno));
187 exit(16);
188 }
189
190 // Unalloc path
191 free(path);
192
193 //------------- Detections -----------------------
194
195 seq = calloc(1, sizeof(vds_sequence_t));
196
197 stats.AVDPSerialNum = 0xFFFF;
198 status = is_udf(dev, &blocksize, force_sectorsize); //this function is checking for UDF recognition sequence. It also tries to detect blocksize
199 if(status < 0) {
200 exit(status);
201 } else if(status == 1) { //Unclosed or bridged medium
202 status = get_avdp(dev, &disc, &blocksize, st_size, -1, force_sectorsize, &stats); //load AVDP and verify blocksize
203 source = FIRST_AVDP; // Unclosed medium have only one AVDP and that is saved at first position.
204 if(status) {
205 err("AVDP is broken. Aborting.\n");
206 exit(4);
207 }
208 } else { //Normal medium
209 seq->anchor[0].error = get_avdp(dev, &disc, &blocksize, st_size, FIRST_AVDP, force_sectorsize, &stats); //try load FIRST AVDP
210 seq->anchor[1].error = get_avdp(dev, &disc, &blocksize, st_size, SECOND_AVDP, force_sectorsize, &stats); //load AVDP
211 seq->anchor[2].error = get_avdp(dev, &disc, &blocksize, st_size, THIRD_AVDP, force_sectorsize, &stats); //load AVDP
212
213 if(seq->anchor[0].error)
214 err("AVDP[0] is broken.\n");
215 if(seq->anchor[1].error)
216 err("AVDP[1] is broken.\n");
217 if(seq->anchor[2].error)
218 err("AVDP[2] is broken.\n");
219
220 if((seq->anchor[0].error & ~E_EXTLEN) == 0) {
221 source = FIRST_AVDP;
222 } else if((seq->anchor[1].error & ~E_EXTLEN) == 0) {
223 source = SECOND_AVDP;
224 } else if((seq->anchor[2].error & ~E_EXTLEN) == 0) {
225 source = THIRD_AVDP;
226 } else {
227 err("All AVDP are broken. Aborting.\n");
228 exit(4);
229 }
230 }
231
232 msg("Sectorsize: %d\n", blocksize);
233
234 if(blocksize == -1) {
235 err("Device blocksize is not defined. Please define it with -b BLOCKSIZE parameter\n");
236 exit(16);
237 }
238
239 // Correct blocksize MUST be blocksize%512 == 0. We keep definitive list for now.
240 if(!(blocksize == 512 | blocksize == 1024 | blocksize == 2048 | blocksize == 4096)) {
241 err("Invalid blocksize. Posible blocksizes must be dividable by 512.\n");
242 exit(16);
243 }
244
245 note("\nTrying to load VDS\n");
246 status |= get_vds(dev, &disc, blocksize, source, MAIN_VDS, seq); //load main VDS
247 status |= get_vds(dev, &disc, blocksize, source, RESERVE_VDS, seq); //load reserve VDS
248
249 verify_vds(&disc, MAIN_VDS, seq);
250 verify_vds(&disc, RESERVE_VDS, seq);
251
252 status |= get_lvid(dev, &disc, blocksize, &stats, seq); //load LVID
253 if(stats.minUDFReadRev > MAX_VERSION){
254 err("Medium UDF revision is %04x and we are able to check up to %04x\n", stats.minUDFReadRev, MAX_VERSION);
255 exit(8);
256 }
257
258 #ifdef PRINT_DISC
259 print_disc(&disc);
260 #endif
261
262 stats.blocksize = blocksize;
263
264 if(get_pd(dev, &disc, blocksize, &stats, seq)) {
265 err("PD error\n");
266 exit(8);
267 }
268
269 uint32_t lbnlsn = 0;
270 dbg("STATUS: 0x%02x\n", status);
271 status |= get_fsd(dev, &disc, blocksize, &lbnlsn, &stats, seq);
272 dbg("STATUS: 0x%02x\n", status);
273 if(status >= 8) {
274 err("Unable to continue without FSD. Consider submitting bug report. Exiting.\n");
275 exit(status);
276 }
277
278 note("LBNLSN: %d\n", lbnlsn);
279 status |= get_file_structure(dev, &disc, lbnlsn, &stats, seq);
280
281 dbg("USD Alloc Descs\n");
282 extent_ad *usdext;
283 uint8_t *usdarr;
284 for(int i=0; i<disc.udf_usd[0]->numAllocDescs; i++) {
285 usdext = &disc.udf_usd[0]->allocDescs[i];
286 dbg("Len: %d, Loc: 0x%x\n",usdext->extLength, usdext->extLocation);
287 dbg("LSN loc: 0x%x\n", lbnlsn+usdext->extLocation);
288 usdarr = (dev+(lbnlsn + usdext->extLocation)*blocksize);
289 }
290
291 dbg("PD PartitionsContentsUse\n");
292 for(int i=0; i<128; ) {
293 for(int j=0; j<8; j++, i++) {
294 note("%02x ", disc.udf_pd[0]->partitionContentsUse[i]);
295 }
296 note("\n");
297 }
298 get_volume_identifier(&disc, &stats, seq);
299
300 uint64_t countedBits = count_used_bits(&stats);
301 dbg("**** BITMAP USED SPACE: %d ****\n", countedBits);
302
303 //---------- Corrections --------------
304 msg("\nFilesystem status\n-----------------\n");
305 msg("Volume set identifier: %s\n", stats.volumeSetIdent);
306 msg("Partition identifier: %s\n", stats.partitionIdent);
307 msg("Next UniqueID: %d\n", stats.actUUID);
308 msg("Max found UniqueID: %d\n", stats.maxUUID);
309 msg("Last LVID recoreded change: %s\n", print_timestamp(stats.LVIDtimestamp));
310 msg("expected number of files: %d\n", stats.expNumOfFiles);
311 msg("expected number of dirs: %d\n", stats.expNumOfDirs);
312 msg("counted number of files: %d\n", stats.countNumOfFiles);
313 msg("counted number of dirs: %d\n", stats.countNumOfDirs);
314 if(stats.expNumOfDirs != stats.countNumOfDirs || stats.expNumOfFiles != stats.countNumOfFiles) {
315 seq->lvid.error |= E_FILES;
316 }
317 msg("UDF rev: min read: %04x\n", stats.minUDFReadRev);
318 msg(" min write: %04x\n", stats.minUDFWriteRev);
319 msg(" max write: %04x\n", stats.maxUDFWriteRev);
320 msg("Used Space: %lu (%lu)\n", stats.usedSpace, stats.usedSpace/blocksize);
321 msg("Free Space: %lu (%lu)\n", stats.freeSpaceBlocks*blocksize, stats.freeSpaceBlocks);
322 msg("Partition size: %lu (%lu)\n", stats.partitionSizeBlocks*blocksize, stats.partitionSizeBlocks);
323 uint64_t expUsedSpace = (stats.partitionSizeBlocks-stats.freeSpaceBlocks)*blocksize;
324 msg("Expected Used Space: %lu (%lu)\n", expUsedSpace, expUsedSpace/blocksize);
325 msg("Expected Used Blocks: %d\nExpected Unused Blocks: %d\n", stats.expUsedBlocks, stats.expUnusedBlocks);
326 int64_t usedSpaceDiff = expUsedSpace-stats.usedSpace;
327 if(usedSpaceDiff != 0) {
328 err("%d blocks is unused but not marked as unallocated in Free Space Table.\n", usedSpaceDiff/blocksize);
329 err("Correct free space: %lu\n", stats.freeSpaceBlocks + usedSpaceDiff/blocksize);
330 seq->lvid.error |= E_FREESPACE;
331 }
332 int32_t usedSpaceDiffBlocks = stats.expUsedBlocks - countedBits;//stats.usedSpace/blocksize;
333 if(usedSpaceDiffBlocks != 0) {
334 err("%d blocks is unused but not marked as unallocated in SBD.\n", usedSpaceDiffBlocks);
335 seq->pd.error |= E_FREESPACE;
336 }
337
338 if(seq->anchor[0].error + seq->anchor[1].error + seq->anchor[2].error != 0) { //Something went wrong with AVDPs
339 int target1 = -1;
340 int target2 = -1;
341
342 if((seq->anchor[0].error & ~E_EXTLEN) == 0) {
343 source = FIRST_AVDP;
344 if((seq->anchor[1].error & ~E_EXTLEN) != 0)
345 target1 = SECOND_AVDP;
346 if((seq->anchor[2].error & ~E_EXTLEN) != 0)
347 target2 = THIRD_AVDP;
348 } else if((seq->anchor[1].error & ~E_EXTLEN) == 0) {
349 source = SECOND_AVDP;
350 target1 = FIRST_AVDP;
351 if((seq->anchor[2].error & ~E_EXTLEN) != 0)
352 target2 = THIRD_AVDP;
353 } else if((seq->anchor[2].error & ~E_EXTLEN) == 0) {
354 source = THIRD_AVDP;
355 target1 = FIRST_AVDP;
356 target2 = SECOND_AVDP;
357 } else {
358 err("Unrecoverable AVDP failure. Aborting.\n");
359 exit(4);
360 }
361
362 if(target1 >= 0)
363 error_status |= ES_AVDP1;
364
365 if(target2 >= 0)
366 error_status |= ES_AVDP2;
367
368 int fixavdp = 0;
369 if(interactive) {
370 if(prompt("Found error at AVDP. Do you want to fix them? [Y/n]") != 0) {
371 fixavdp = 1;
372 }
373 }
374 if(autofix)
375 fixavdp = 1;
376
377
378 if(fixavdp) {
379 msg("Source: %d, Target1: %d, Target2: %d\n", source, target1, target2);
380 if(target1 >= 0) {
381 if(write_avdp(dev, &disc, blocksize, st_size, source, target1) != 0) {
382 fatal("AVDP recovery failed. Is medium writable?\n");
383 } else {
384 imp("AVDP recovery was successful.\n");
385 error_status &= ~ES_AVDP1;
386 fix_status |= ES_AVDP1;
387 }
388 }
389 if(target2 >= 0) {
390 if(write_avdp(dev, &disc, blocksize, st_size, source, target2) != 0) {
391 fatal("AVDP recovery failed. Is medium writable?\n");
392 } else {
393 imp("AVDP recovery was successful.\n");
394 error_status &= ~ES_AVDP2;
395 fix_status |= ES_AVDP2;
396 }
397 }
398 }
399
400 if(fixavdp) {
401 if(seq->anchor[0].error & E_EXTLEN) {
402 status |= fix_avdp(dev, &disc, blocksize, st_size, FIRST_AVDP);
403 }
404 if(seq->anchor[1].error & E_EXTLEN) {
405 status |= fix_avdp(dev, &disc, blocksize, st_size, SECOND_AVDP);
406 }
407 if(seq->anchor[2].error & E_EXTLEN) {
408 status |= fix_avdp(dev, &disc, blocksize, st_size, THIRD_AVDP);
409 }
410 }
411
412 }
413
414
415 print_metadata_sequence(seq);
416
417 status |= fix_vds(dev, &disc, blocksize, source, seq);
418
419 int fixlvid = 0;
420 int fixpd = 0;
421 int lviderr = 0;
422 if(seq->lvid.error == (E_CRC | E_CHECKSUM)) {
423 //LVID is doomed.
424 err("LVID is broken. Recovery is not possible.\n");
425 error_status |= ES_LVID;
426 } else {
427 if(stats.maxUUID >= stats.actUUID || (seq->lvid.error & E_UUID)) {
428 err("Max found Unique ID is same or bigger that Unique ID found at LVID.\n");
429 lviderr = 1;
430 }
431 if(disc.udf_lvid->integrityType != LVID_INTEGRITY_TYPE_CLOSE) {
432 //There are some unfinished writes
433 err("Opened integrity type. Some writes may be unfinished.\n");
434 lviderr = 1;
435 }
436 if(seq->lvid.error & E_TIMESTAMP) {
437 err("LVID timestamp is older than timestamps of files.\n");
438 lviderr=1;
439 }
440 if(seq->lvid.error & E_FILES) {
441 err("Number of files or directories is not corresponding to counted number\n");
442 lviderr=1;
443 }
444 if(seq->lvid.error & E_FREESPACE) {
445 err("Free Space table is not corresponding to reality.\n");
446 lviderr=1;
447 }
448
449 if(lviderr) {
450 error_status |= ES_LVID;
451 if(interactive) {
452 if(prompt("Fix it? [Y/n]") != 0) {
453 fixlvid = 1;
454 }
455 }
456 if(autofix)
457 fixlvid = 1;
458 }
459 }
460
461 if(seq->pd.error != 0) {
462 error_status |= ES_PD;
463 if(interactive) {
464 if(prompt("Fix SBD? [Y/n]") != 0)
465 fixpd = 1;
466 }
467 if(autofix)
468 fixpd = 1;
469 }
470
471
472 if(fixlvid == 1) {
473 if(fix_lvid(dev, &disc, blocksize, &stats, seq) == 0) {
474 error_status &= ~(ES_LVID | ES_PD);
475 fix_status |= (ES_LVID | ES_PD);
476 }
477 } else if(fixlvid == 0 && fixpd == 1) {
478 if(fix_pd(dev, &disc, blocksize, &stats, seq) == 0) {
479 error_status &= ~(ES_PD);
480 fix_status |= ES_PD;
481 }
482 }
483
484 #if DEBUG && 0
485 note("\n ACT \t EXP\n");
486 uint32_t shift = 0;
487 uint32_t line = 0;
488 uint32_t amount = 50000;
489 for(int i=0+shift, k=0+shift; i<stats.partitionSizeBlocks/8 && i < amount+shift; ) {
490 note("[%04d] ",line++);
491 for(int j=0; j<16; j++, i++) {
492 note("%02x ", stats.actPartitionBitmap[i]);
493 }
494 note("| ");
495 for(int j=0; j<16; j++, k++) {
496 note("%02x ", stats.expPartitionBitmap[k]);
497 }
498 note("\n");
499 }
500 #endif
501
502 //---------------- Error & Fix Status -------------
503 if(error_status != 0) {
504 status |= 4; //Errors remained unfixed
505 }
506
507 if(fix_status != 0) {
508 status |= 1; // Errors were fixed
509 }
510
511 //---------------- Clean up -----------------
512
513 note("Clean allocations\n");
514 free(disc.udf_anchor[0]);
515 free(disc.udf_anchor[1]);
516 free(disc.udf_anchor[2]);
517
518 free(disc.udf_pvd[0]);
519 free(disc.udf_lvd[0]);
520 free(disc.udf_usd[0]);
521 free(disc.udf_iuvd[0]);
522 free(disc.udf_pd[0]);
523 free(disc.udf_td[0]);
524
525 free(disc.udf_pvd[1]);
526 free(disc.udf_lvd[1]);
527 free(disc.udf_usd[1]);
528 free(disc.udf_iuvd[1]);
529 free(disc.udf_pd[1]);
530 free(disc.udf_td[1]);
531
532 free(disc.udf_lvid);
533 free(disc.udf_fsd);
534
535 free(seq);
536 free(stats.actPartitionBitmap);
537
538 flock(fd, LOCK_UN);
539 close(fd);
540 fclose(fp);
541
542 msg("All done\n");
543 return status;
544 }
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
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
filesystemStats
Definition: udffsck.h:71
partitionDesc::partitionContentsUse
uint8_t partitionContentsUse[128]
Definition: ecma_167.h:267
filesystemStats::blocksize
uint16_t blocksize
Definition: udffsck.h:72
vds_sequence_t
Definition: udffsck.h:56
vds_sequence_t::anchor
metadata_t anchor[3]
Definition: udffsck.h:57
line
char line[256]
Definition: wrudf.c:27
udf_disc::blocksize
uint16_t blocksize
Definition: libudffs.h:98
udf_disc::udf_lvid
struct logicalVolIntegrityDesc * udf_lvid
Definition: libudffs.h:118
main
int main(int argc, char *argv[])
Definition: main.c:237
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
ES_LVID
#define ES_LVID
Definition: main.c:77
udf_disc::udf_pd
struct partitionDesc * udf_pd[2]
Definition: libudffs.h:114
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
THIRD_AVDP
Definition: udffsck.h:42
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
ecma_167.h
unallocSpaceDesc::numAllocDescs
uint32_t numAllocDescs
Definition: ecma_167.h:348
E_CHECKSUM
#define E_CHECKSUM
Definition: udffsck.h:118
filesystemStats::usedSpace
uint64_t usedSpace
Definition: udffsck.h:83
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
flags
uint16_t flags
Definition: ecma_167.h:75
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
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
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
udf_disc::udf_anchor
struct anchorVolDescPtr * udf_anchor[3]
Definition: libudffs.h:111
note
void note(const char *format,...)
Note output.
Definition: utils.c:328
ES_PD
#define ES_PD
Definition: main.c:76
autofix
int autofix
Definition: options.c:34
filesystemStats::countNumOfDirs
uint32_t countNumOfDirs
Definition: udffsck.h:78
verbosity
verbosity_e verbosity
Definition: utils.c:49
E_TIMESTAMP
#define E_TIMESTAMP
Definition: udffsck.h:123
utils.h
dbg
void dbg(const char *format,...)
Debug output.
Definition: utils.c:296
filesystemStats::AVDPSerialNum
uint16_t AVDPSerialNum
Definition: udffsck.h:82
MAX_VERSION
#define MAX_VERSION
Definition: main.c:50
filesystemStats::actUUID
uint64_t actUUID
Definition: udffsck.h:73
FIRST_AVDP
Definition: udffsck.h:40
is_udf
int is_udf(uint8_t *dev, int *sectorsize, int force_sectorsize)
UDF VRS detection function.
Definition: udffsck.c:347
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
MAIN_VDS
Definition: udffsck.h:46
unallocSpaceDesc::allocDescs
extent_ad allocDescs[0]
Definition: ecma_167.h:349
udf_disc::udf_usd
struct unallocSpaceDesc * udf_usd[2]
Definition: libudffs.h:115
filesystemStats::actPartitionBitmap
uint8_t * actPartitionBitmap
Definition: udffsck.h:90
options.h
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
print_metadata_sequence
void print_metadata_sequence(vds_sequence_t *seq)
Prints metadata error sequence.
Definition: utils.c:440
filesystemStats::countNumOfFiles
uint32_t countNumOfFiles
Definition: udffsck.h:76
vds_sequence_t::lvid
metadata_t lvid
Definition: udffsck.h:60
filesystemStats::expNumOfDirs
uint32_t expNumOfDirs
Definition: udffsck.h:77
E_FREESPACE
#define E_FREESPACE
Definition: udffsck.h:124
E_FILES
#define E_FILES
Definition: udffsck.h:125
ES_AVDP1
#define ES_AVDP1
Definition: main.c:74
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
vds_sequence_t::pd
metadata_t pd
Definition: udffsck.h:61
filesystemStats::expPartitionBitmap
uint8_t * expPartitionBitmap
Definition: udffsck.h:91
ES_AVDP2
#define ES_AVDP2
Definition: main.c:75
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
udf_disc::udf_td
struct terminatingDesc * udf_td[2]
Definition: libudffs.h:117
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
udffsck.h
filesystemStats::expNumOfFiles
uint32_t expNumOfFiles
Definition: udffsck.h:75
parse_args
void parse_args(int argc, char *argv[], struct cdrw_disc *disc, char *device)
Definition: options.c:69
print_disc
int print_disc(struct udf_disc *disc)
Support function printing VDS, AVDP and LVID.
Definition: utils.c:102
udf_disc
Definition: libudffs.h:95
E_CRC
#define E_CRC
Definition: udffsck.h:119
filesystemStats::freeSpaceBlocks
uint32_t freeSpaceBlocks
Definition: udffsck.h:84
filesystemStats::expUnusedBlocks
uint32_t expUnusedBlocks
Definition: udffsck.h:87
libudffs.h
err
void err(const char *format,...)
Error output.
Definition: utils.c:392
logicalVolIntegrityDesc::integrityType
uint32_t integrityType
Definition: ecma_167.h:364
imp
void imp(const char *format,...)
Important message output.
Definition: utils.c:360
warn
void warn(const char *format,...)
Warning output.
Definition: utils.c:376
SECOND_AVDP
Definition: udffsck.h:41
filesystemStats::maxUDFWriteRev
uint16_t maxUDFWriteRev
Definition: udffsck.h:81
print_timestamp
char * print_timestamp(timestamp ts)
Timestamp printing function.
Definition: udffsck.c:170
E_EXTLEN
#define E_EXTLEN
Definition: udffsck.h:126
udf_disc::udf_fsd
struct fileSetDesc * udf_fsd
Definition: libudffs.h:125
segv_interrupt
void segv_interrupt(int dummy)
Segmentation fault handler.
Definition: main.c:68
filesystemStats::minUDFReadRev
uint16_t minUDFReadRev
Definition: udffsck.h:79
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
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
user_interrupt
void user_interrupt(int dummy)
User interrupt hander (Ctrl + C or SIGINT)
Definition: main.c:57
udf_disc::udf_lvd
struct logicalVolDesc * udf_lvd[2]
Definition: libudffs.h:113
fatal
void fatal(const char *format,...)
Fatal Error output.
Definition: utils.c:408
LVID_INTEGRITY_TYPE_CLOSE
#define LVID_INTEGRITY_TYPE_CLOSE
Definition: ecma_167.h:376
filesystemStats::expUsedBlocks
uint32_t expUsedBlocks
Definition: udffsck.h:86
udf_disc::udf_iuvd
struct impUseVolDesc * udf_iuvd[2]
Definition: libudffs.h:116
filesystemStats::partitionIdent
dstring * partitionIdent
Definition: udffsck.h:93
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