/* * isosize.c - Andries Brouwer, 000608 * * use header info to find size of iso9660 file system * output a number - useful in scripts * * Synopsis: * isosize [-x] [-d ] * where "-x" gives length in sectors and sector size while * without this argument the size is given in bytes * without "-x" gives length in bytes unless "-d " is * given. In the latter case the length in bytes divided * by is given * * Version 2.03 2000/12/21 * - add "-d " option and use long long to fix things > 2 GB * Version 2.02 2000/10/11 * - error messages on IO failures [D. Gilbert] * */ #include #include #include #include #include #include #include "nls.h" #include "c.h" #include "strutils.h" #include "closestream.h" #include "iso9660.h" #define ISOSIZE_EXIT_ALLFAILED 32 #define ISOSIZE_EXIT_SOMEOK 64 static int is_iso(int fd) { char label[8]; if (pread(fd, &label, 8, 0x8000) == -1) return 1; return memcmp(&label, &"\1CD001\1", 8); } static int isosize(int argc, char *filenamep, int xflag, long divisor) { int fd, nsecs, ssize, rc = -1; unsigned char volume_space_size[8]; unsigned char logical_block_size[4]; if ((fd = open(filenamep, O_RDONLY)) < 0) { warn(_("cannot open %s"), filenamep); goto done; } if (is_iso(fd)) warnx(_("%s: might not be an ISO filesystem"), filenamep); if (pread(fd, volume_space_size, sizeof(volume_space_size), 0x8050) != sizeof(volume_space_size) || pread(fd, logical_block_size, sizeof(logical_block_size), 0x8080) != sizeof(logical_block_size)) { if (errno) warn(_("read error on %s"), filenamep); else warnx(_("read error on %s"), filenamep); goto done; } nsecs = isonum_733(volume_space_size, xflag); /* isonum_723 returns nowadays always 2048 */ ssize = isonum_723(logical_block_size, xflag); if (1 < argc) printf("%s: ", filenamep); if (xflag) printf(_("sector count: %d, sector size: %d\n"), nsecs, ssize); else { long long product = nsecs; if (divisor == 0) printf("%lld\n", product * ssize); else if (divisor == ssize) printf("%d\n", nsecs); else printf("%lld\n", (product * ssize) / divisor); } rc = 0; done: if (fd >= 0) close(fd); return rc; } static void __attribute__((__noreturn__)) usage(void) { fputs(USAGE_HEADER, stdout); fprintf(stdout, _(" %s [options] ...\n"), program_invocation_short_name); fputs(USAGE_SEPARATOR, stdout); fputs(_("Show the length of an ISO-9660 filesystem.\n"), stdout); fputs(USAGE_OPTIONS, stdout); fputs(_(" -d, --divisor= divide the amount of bytes by \n"), stdout); fputs(_(" -x, --sectors show sector count and size\n"), stdout); printf(USAGE_HELP_OPTIONS(25)); printf(USAGE_MAN_TAIL("isosize(8)")); exit(EXIT_SUCCESS); } int main(int argc, char **argv) { int j, ct_err = 0, ct, opt, xflag = 0; long divisor = 0; static const struct option longopts[] = { {"divisor", required_argument, NULL, 'd'}, {"sectors", no_argument, NULL, 'x'}, {"version", no_argument, NULL, 'V'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); close_stdout_atexit(); while ((opt = getopt_long(argc, argv, "d:xVh", longopts, NULL)) != -1) { switch (opt) { case 'd': divisor = strtol_or_err(optarg, _("invalid divisor argument")); break; case 'x': xflag = 1; break; case 'V': print_version(EXIT_SUCCESS); case 'h': usage(); default: errtryhelp(EXIT_FAILURE); } } ct = argc - optind; if (ct <= 0) { warnx(_("no device specified")); errtryhelp(EXIT_FAILURE); } for (j = optind; j < argc; j++) { if (isosize(ct, argv[j], xflag, divisor) != 0) ct_err++; } return ct == ct_err ? ISOSIZE_EXIT_ALLFAILED : /* all failed */ ct_err ? ISOSIZE_EXIT_SOMEOK : /* some ok */ EXIT_SUCCESS; /* all success */ }