]> git.ipfire.org Git - thirdparty/util-linux.git/blob - disk-utils/isosize.c
Merge branch 'vla-alloca' of https://github.com/t-8ch/util-linux
[thirdparty/util-linux.git] / disk-utils / isosize.c
1 /*
2 * isosize.c - Andries Brouwer, 000608
3 *
4 * use header info to find size of iso9660 file system
5 * output a number - useful in scripts
6 *
7 * Synopsis:
8 * isosize [-x] [-d <num>] <filename>
9 * where "-x" gives length in sectors and sector size while
10 * without this argument the size is given in bytes
11 * without "-x" gives length in bytes unless "-d <num>" is
12 * given. In the latter case the length in bytes divided
13 * by <num> is given
14 *
15 * Version 2.03 2000/12/21
16 * - add "-d <num>" option and use long long to fix things > 2 GB
17 * Version 2.02 2000/10/11
18 * - error messages on IO failures [D. Gilbert]
19 *
20 */
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <getopt.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <errno.h>
27
28 #include "nls.h"
29 #include "c.h"
30 #include "strutils.h"
31 #include "closestream.h"
32 #include "iso9660.h"
33
34 #define ISOSIZE_EXIT_ALLFAILED 32
35 #define ISOSIZE_EXIT_SOMEOK 64
36
37 static int is_iso(int fd)
38 {
39 char label[8];
40
41 if (pread(fd, &label, 8, 0x8000) == -1)
42 return 1;
43 return memcmp(&label, &"\1CD001\1", 8);
44 }
45
46 static int isosize(int argc, char *filenamep, int xflag, long divisor)
47 {
48 int fd, nsecs, ssize, rc = -1;
49 unsigned char volume_space_size[8];
50 unsigned char logical_block_size[4];
51
52 if ((fd = open(filenamep, O_RDONLY)) < 0) {
53 warn(_("cannot open %s"), filenamep);
54 goto done;
55 }
56 if (is_iso(fd))
57 warnx(_("%s: might not be an ISO filesystem"), filenamep);
58
59 if (pread(fd, volume_space_size, sizeof(volume_space_size), 0x8050) != sizeof(volume_space_size) ||
60 pread(fd, logical_block_size, sizeof(logical_block_size), 0x8080) != sizeof(logical_block_size)) {
61 if (errno)
62 warn(_("read error on %s"), filenamep);
63 else
64 warnx(_("read error on %s"), filenamep);
65 goto done;
66 }
67
68 nsecs = isonum_733(volume_space_size, xflag);
69 /* isonum_723 returns nowadays always 2048 */
70 ssize = isonum_723(logical_block_size, xflag);
71
72 if (1 < argc)
73 printf("%s: ", filenamep);
74 if (xflag)
75 printf(_("sector count: %d, sector size: %d\n"), nsecs, ssize);
76 else {
77 long long product = nsecs;
78
79 if (divisor == 0)
80 printf("%lld\n", product * ssize);
81 else if (divisor == ssize)
82 printf("%d\n", nsecs);
83 else
84 printf("%lld\n", (product * ssize) / divisor);
85 }
86
87 rc = 0;
88 done:
89 if (fd >= 0)
90 close(fd);
91 return rc;
92 }
93
94 static void __attribute__((__noreturn__)) usage(void)
95 {
96
97 fputs(USAGE_HEADER, stdout);
98 fprintf(stdout,
99 _(" %s [options] <iso9660_image_file> ...\n"),
100 program_invocation_short_name);
101
102 fputs(USAGE_SEPARATOR, stdout);
103 fputs(_("Show the length of an ISO-9660 filesystem.\n"), stdout);
104
105 fputs(USAGE_OPTIONS, stdout);
106 fputs(_(" -d, --divisor=<number> divide the amount of bytes by <number>\n"), stdout);
107 fputs(_(" -x, --sectors show sector count and size\n"), stdout);
108
109 printf(USAGE_HELP_OPTIONS(25));
110 printf(USAGE_MAN_TAIL("isosize(8)"));
111
112 exit(EXIT_SUCCESS);
113 }
114
115 int main(int argc, char **argv)
116 {
117 int j, ct_err = 0, ct, opt, xflag = 0;
118 long divisor = 0;
119
120 static const struct option longopts[] = {
121 {"divisor", required_argument, NULL, 'd'},
122 {"sectors", no_argument, NULL, 'x'},
123 {"version", no_argument, NULL, 'V'},
124 {"help", no_argument, NULL, 'h'},
125 {NULL, 0, NULL, 0}
126 };
127
128 setlocale(LC_ALL, "");
129 bindtextdomain(PACKAGE, LOCALEDIR);
130 textdomain(PACKAGE);
131 close_stdout_atexit();
132
133 while ((opt = getopt_long(argc, argv, "d:xVh", longopts, NULL)) != -1) {
134 switch (opt) {
135 case 'd':
136 divisor =
137 strtol_or_err(optarg,
138 _("invalid divisor argument"));
139 break;
140 case 'x':
141 xflag = 1;
142 break;
143 case 'V':
144 print_version(EXIT_SUCCESS);
145 case 'h':
146 usage();
147 default:
148 errtryhelp(EXIT_FAILURE);
149 }
150 }
151
152 ct = argc - optind;
153
154 if (ct <= 0) {
155 warnx(_("no device specified"));
156 errtryhelp(EXIT_FAILURE);
157 }
158
159 for (j = optind; j < argc; j++) {
160 if (isosize(ct, argv[j], xflag, divisor) != 0)
161 ct_err++;
162 }
163
164 return ct == ct_err ? ISOSIZE_EXIT_ALLFAILED : /* all failed */
165 ct_err ? ISOSIZE_EXIT_SOMEOK : /* some ok */
166 EXIT_SUCCESS; /* all success */
167 }