]> git.ipfire.org Git - thirdparty/util-linux.git/blob - disk-utils/isosize.c
Merge branch 'meson-more-build-options' of https://github.com/jwillikers/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
33 #define ISOSIZE_EXIT_ALLFAILED 32
34 #define ISOSIZE_EXIT_SOMEOK 64
35
36 static int is_iso(int fd)
37 {
38 char label[8];
39
40 if (pread(fd, &label, 8, 0x8000) == -1)
41 return 1;
42 return memcmp(&label, &"\1CD001\1", 8);
43 }
44
45 static int isonum_721(unsigned char *p)
46 {
47 return ((p[0] & 0xff)
48 | ((p[1] & 0xff) << 8));
49 }
50
51 static int isonum_722(unsigned char *p)
52 {
53 return ((p[1] & 0xff)
54 | ((p[0] & 0xff) << 8));
55 }
56
57 static int isonum_723(unsigned char *p, int xflag)
58 {
59 int le = isonum_721(p);
60 int be = isonum_722(p + 2);
61
62 if (xflag && le != be)
63 /* translation is useless */
64 warnx("723error: le=%d be=%d", le, be);
65 return (le);
66 }
67
68 static int isonum_731(unsigned char *p)
69 {
70 return ((p[0] & 0xff)
71 | ((p[1] & 0xff) << 8)
72 | ((p[2] & 0xff) << 16)
73 | ((p[3] & 0xff) << 24));
74 }
75
76 static int isonum_732(unsigned char *p)
77 {
78 return ((p[3] & 0xff)
79 | ((p[2] & 0xff) << 8)
80 | ((p[1] & 0xff) << 16)
81 | ((p[0] & 0xff) << 24));
82 }
83
84 static int isonum_733(unsigned char *p, int xflag)
85 {
86 int le = isonum_731(p);
87 int be = isonum_732(p + 4);
88
89 if (xflag && le != be)
90 /* translation is useless */
91 warnx("733error: le=%d be=%d", le, be);
92 return (le);
93 }
94
95 static int isosize(int argc, char *filenamep, int xflag, long divisor)
96 {
97 int fd, nsecs, ssize, rc = -1;
98 unsigned char volume_space_size[8];
99 unsigned char logical_block_size[4];
100
101 if ((fd = open(filenamep, O_RDONLY)) < 0) {
102 warn(_("cannot open %s"), filenamep);
103 goto done;
104 }
105 if (is_iso(fd))
106 warnx(_("%s: might not be an ISO filesystem"), filenamep);
107
108 if (pread(fd, volume_space_size, sizeof(volume_space_size), 0x8050) != sizeof(volume_space_size) ||
109 pread(fd, logical_block_size, sizeof(logical_block_size), 0x8080) != sizeof(logical_block_size)) {
110 if (errno)
111 warn(_("read error on %s"), filenamep);
112 else
113 warnx(_("read error on %s"), filenamep);
114 goto done;
115 }
116
117 nsecs = isonum_733(volume_space_size, xflag);
118 /* isonum_723 returns nowadays always 2048 */
119 ssize = isonum_723(logical_block_size, xflag);
120
121 if (1 < argc)
122 printf("%s: ", filenamep);
123 if (xflag)
124 printf(_("sector count: %d, sector size: %d\n"), nsecs, ssize);
125 else {
126 long long product = nsecs;
127
128 if (divisor == 0)
129 printf("%lld\n", product * ssize);
130 else if (divisor == ssize)
131 printf("%d\n", nsecs);
132 else
133 printf("%lld\n", (product * ssize) / divisor);
134 }
135
136 rc = 0;
137 done:
138 if (fd >= 0)
139 close(fd);
140 return rc;
141 }
142
143 static void __attribute__((__noreturn__)) usage(void)
144 {
145
146 fputs(USAGE_HEADER, stdout);
147 fprintf(stdout,
148 _(" %s [options] <iso9660_image_file> ...\n"),
149 program_invocation_short_name);
150
151 fputs(USAGE_SEPARATOR, stdout);
152 fputs(_("Show the length of an ISO-9660 filesystem.\n"), stdout);
153
154 fputs(USAGE_OPTIONS, stdout);
155 fputs(_(" -d, --divisor=<number> divide the amount of bytes by <number>\n"), stdout);
156 fputs(_(" -x, --sectors show sector count and size\n"), stdout);
157
158 printf(USAGE_HELP_OPTIONS(25));
159 printf(USAGE_MAN_TAIL("isosize(8)"));
160
161 exit(EXIT_SUCCESS);
162 }
163
164 int main(int argc, char **argv)
165 {
166 int j, ct_err = 0, ct, opt, xflag = 0;
167 long divisor = 0;
168
169 static const struct option longopts[] = {
170 {"divisor", required_argument, NULL, 'd'},
171 {"sectors", no_argument, NULL, 'x'},
172 {"version", no_argument, NULL, 'V'},
173 {"help", no_argument, NULL, 'h'},
174 {NULL, 0, NULL, 0}
175 };
176
177 setlocale(LC_ALL, "");
178 bindtextdomain(PACKAGE, LOCALEDIR);
179 textdomain(PACKAGE);
180 close_stdout_atexit();
181
182 while ((opt = getopt_long(argc, argv, "d:xVh", longopts, NULL)) != -1) {
183 switch (opt) {
184 case 'd':
185 divisor =
186 strtol_or_err(optarg,
187 _("invalid divisor argument"));
188 break;
189 case 'x':
190 xflag = 1;
191 break;
192 case 'V':
193 print_version(EXIT_SUCCESS);
194 case 'h':
195 usage();
196 default:
197 errtryhelp(EXIT_FAILURE);
198 }
199 }
200
201 ct = argc - optind;
202
203 if (ct <= 0) {
204 warnx(_("no device specified"));
205 errtryhelp(EXIT_FAILURE);
206 }
207
208 for (j = optind; j < argc; j++) {
209 if (isosize(ct, argv[j], xflag, divisor) != 0)
210 ct_err++;
211 }
212
213 return ct == ct_err ? ISOSIZE_EXIT_ALLFAILED : /* all failed */
214 ct_err ? ISOSIZE_EXIT_SOMEOK : /* some ok */
215 EXIT_SUCCESS; /* all success */
216 }