]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - disk-utils/isosize.c
wipefs: add --lock and LOCK_BLOCK_DEVICE
[thirdparty/util-linux.git] / disk-utils / isosize.c
index 625dd427e7baaf1fc5ff9ff5f884891d0395d5ca..92996635684310a145330326ef66e1c2b4d1980e 100644 (file)
 #include "c.h"
 #include "strutils.h"
 #include "closestream.h"
+#include "iso9660.h"
 
-#define ISODCL(from, to) (to - from + 1)
+#define ISOSIZE_EXIT_ALLFAILED 32
+#define ISOSIZE_EXIT_SOMEOK    64
 
-static int isonum_721(unsigned char *p)
+static int is_iso(int fd)
 {
-       return ((p[0] & 0xff)
-               | ((p[1] & 0xff) << 8));
-}
-
-static int isonum_722(unsigned char *p)
-{
-       return ((p[1] & 0xff)
-               | ((p[0] & 0xff) << 8));
-}
-
-static int isonum_723(unsigned char *p, int xflag)
-{
-       int le = isonum_721(p);
-       int be = isonum_722(p + 2);
-       if (xflag && le != be)
-               /* translation is useless */
-               warnx("723error: le=%d be=%d", le, be);
-       return (le);
-}
-
-static int isonum_731(unsigned char *p)
-{
-       return ((p[0] & 0xff)
-               | ((p[1] & 0xff) << 8)
-               | ((p[2] & 0xff) << 16)
-               | ((p[3] & 0xff) << 24));
-}
-
-static int isonum_732(unsigned char *p)
-{
-       return ((p[3] & 0xff)
-               | ((p[2] & 0xff) << 8)
-               | ((p[1] & 0xff) << 16)
-               | ((p[0] & 0xff) << 24));
-}
+       char label[8];
 
-static int isonum_733(unsigned char *p, int xflag)
-{
-       int le = isonum_731(p);
-       int be = isonum_732(p + 4);
-       if (xflag && le != be)
-               /* translation is useless */
-               warn("733error: le=%d be=%d", le, be);
-       return (le);
+       if (pread(fd, &label, 8, 0x8000) == -1)
+               return 1;
+       return memcmp(&label, &"\1CD001\1", 8);
 }
 
-struct iso_primary_descriptor
-{
-       unsigned char type                      [ISODCL (   1,    1)]; /* 711 */
-       unsigned char id                        [ISODCL (   2,    6)];
-       unsigned char version                   [ISODCL (   7,    7)]; /* 711 */
-       unsigned char unused1                   [ISODCL (   8,    8)];
-       unsigned char system_id                 [ISODCL (   9,   40)]; /* auchars */
-       unsigned char volume_id                 [ISODCL (  41,   72)]; /* duchars */
-       unsigned char unused2                   [ISODCL (  73,   80)];
-       unsigned char volume_space_size         [ISODCL (  81,   88)]; /* 733 */
-       unsigned char unused3                   [ISODCL (  89,  120)];
-       unsigned char volume_set_size           [ISODCL ( 121,  124)]; /* 723 */
-       unsigned char volume_sequence_number    [ISODCL ( 125,  128)]; /* 723 */
-       unsigned char logical_block_size        [ISODCL ( 129,  132)]; /* 723 */
-       unsigned char path_table_size           [ISODCL ( 133,  140)]; /* 733 */
-       unsigned char type_l_path_table         [ISODCL ( 141,  144)]; /* 731 */
-       unsigned char opt_type_l_path_table     [ISODCL ( 145,  148)]; /* 731 */
-       unsigned char type_m_path_table         [ISODCL ( 149,  152)]; /* 732 */
-       unsigned char opt_type_m_path_table     [ISODCL ( 153,  156)]; /* 732 */
-       unsigned char root_directory_record     [ISODCL ( 157,  190)]; /* 9.1 */
-       unsigned char volume_set_id             [ISODCL ( 191,  318)]; /* duchars */
-       unsigned char publisher_id              [ISODCL ( 319,  446)]; /* achars */
-       unsigned char preparer_id               [ISODCL ( 447,  574)]; /* achars */
-       unsigned char application_id            [ISODCL ( 575,  702)]; /* achars */
-       unsigned char copyright_file_id         [ISODCL ( 703,  739)]; /* 7.5 dchars */
-       unsigned char abstract_file_id          [ISODCL ( 740,  776)]; /* 7.5 dchars */
-       unsigned char bibliographic_file_id     [ISODCL ( 777,  813)]; /* 7.5 dchars */
-       unsigned char creation_date             [ISODCL ( 814,  830)]; /* 8.4.26.1 */
-       unsigned char modification_date         [ISODCL ( 831,  847)]; /* 8.4.26.1 */
-       unsigned char expiration_date           [ISODCL ( 848,  864)]; /* 8.4.26.1 */
-       unsigned char effective_date            [ISODCL ( 865,  881)]; /* 8.4.26.1 */
-       unsigned char file_structure_version    [ISODCL ( 882,  882)]; /* 711 */
-       unsigned char unused4                   [ISODCL ( 883,  883)];
-       unsigned char application_data          [ISODCL ( 884, 1395)];
-       unsigned char unused5                   [ISODCL (1396, 2048)];
-};
-
-static void isosize(char *filenamep, int xflag, long divisor)
+static int isosize(int argc, char *filenamep, int xflag, long divisor)
 {
-       int fd, nsecs, ssize;
-       struct iso_primary_descriptor ipd;
+       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)
-               err(EXIT_FAILURE, _("cannot open %s"), filenamep);
-
-       if (lseek(fd, 16 << 11, 0) == (off_t) - 1)
-               err(EXIT_FAILURE, _("seek error on %s"), filenamep);
+       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 (read(fd, &ipd, sizeof(ipd)) < 0)
-               err(EXIT_FAILURE, _("read error on %s"), 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(ipd.volume_space_size, xflag);
+       nsecs = isonum_733(volume_space_size, xflag);
        /* isonum_723 returns nowadays always 2048 */
-       ssize = isonum_723(ipd.logical_block_size, xflag);
+       ssize = isonum_723(logical_block_size, xflag);
 
-       if (xflag) {
+       if (1 < argc)
+               printf("%s: ", filenamep);
+       if (xflag)
                printf(_("sector count: %d, sector size: %d\n"), nsecs, ssize);
-       else {
+       else {
                long long product = nsecs;
 
                if (divisor == 0)
@@ -148,45 +84,53 @@ static void isosize(char *filenamep, int xflag, long divisor)
                        printf("%lld\n", (product * ssize) / divisor);
        }
 
-       close(fd);
+       rc = 0;
+done:
+       if (fd >= 0)
+               close(fd);
+       return rc;
 }
 
-static void __attribute__((__noreturn__)) usage(FILE *out)
+static void __attribute__((__noreturn__)) usage(void)
 {
-       fputs(USAGE_HEADER, out);
-       fprintf(out,
-               _(" %s [options] iso9660_image_file\n"),
+
+       fputs(USAGE_HEADER, stdout);
+       fprintf(stdout,
+               _(" %s [options] <iso9660_image_file> ...\n"),
                program_invocation_short_name);
-       fputs(USAGE_OPTIONS, out);
-       fputs(_(" -d, --divisor=NUM      divide bytes NUM\n"), out);
-       fputs(_(" -x, --sectors          show sector count and size\n"), out);
-       fputs(USAGE_SEPARATOR, out);
-       fputs(USAGE_HELP, out);
-       fputs(USAGE_VERSION, out);
-       fprintf(out, USAGE_MAN_TAIL("isosize(8)"));
-
-       exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+
+       fputs(USAGE_SEPARATOR, stdout);
+       fputs(_("Show the length of an ISO-9660 filesystem.\n"), stdout);
+
+       fputs(USAGE_OPTIONS, stdout);
+       fputs(_(" -d, --divisor=<number>  divide the amount of bytes by <number>\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, opt, xflag = 0;
+       int j, ct_err = 0, ct, opt, xflag = 0;
        long divisor = 0;
 
        static const struct option longopts[] = {
-               {"divisor", no_argument, 0, 'd'},
-               {"sectors", no_argument, 0, 'x'},
-               {"version", no_argument, 0, 'V'},
-               {"help", no_argument, 0, 'h'},
-               {NULL, 0, 0, 0}
+               {"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);
-       atexit(close_stdout);
+       close_stdout_atexit();
 
-       while ((opt = getopt_long(argc, argv, "d:xVh", longopts, NULL)) != -1)
+       while ((opt = getopt_long(argc, argv, "d:xVh", longopts, NULL)) != -1) {
                switch (opt) {
                case 'd':
                        divisor =
@@ -197,24 +141,27 @@ int main(int argc, char **argv)
                        xflag = 1;
                        break;
                case 'V':
-                       printf(UTIL_LINUX_VERSION);
-                       return EXIT_SUCCESS;
+                       print_version(EXIT_SUCCESS);
                case 'h':
-                       usage(stdout);
+                       usage();
                default:
-                       usage(stderr);
+                       errtryhelp(EXIT_FAILURE);
                }
+       }
 
        ct = argc - optind;
 
-       if (ct <= 0)
-               usage(stderr);
+       if (ct <= 0) {
+               warnx(_("no device specified"));
+               errtryhelp(EXIT_FAILURE);
+       }
 
        for (j = optind; j < argc; j++) {
-               if (ct > 1)
-                       printf("%s: ", argv[j]);
-               isosize(argv[j], xflag, divisor);
+               if (isosize(ct, argv[j], xflag, divisor) != 0)
+                       ct_err++;
        }
 
-       return EXIT_SUCCESS;
+       return  ct == ct_err    ? ISOSIZE_EXIT_ALLFAILED :      /* all failed */
+               ct_err          ? ISOSIZE_EXIT_SOMEOK :         /* some ok */
+               EXIT_SUCCESS;                                   /* all success */
 }