]>
Commit | Line | Data |
---|---|---|
66ee8158 KZ |
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> | |
4c0ecdd4 | 26 | #include <errno.h> |
66ee8158 KZ |
27 | |
28 | #include "nls.h" | |
73611843 | 29 | #include "c.h" |
ab3a34ff | 30 | #include "strutils.h" |
45ca68ec | 31 | #include "closestream.h" |
66ee8158 | 32 | |
c3801802 KZ |
33 | #define ISOSIZE_EXIT_ALLFAILED 32 |
34 | #define ISOSIZE_EXIT_SOMEOK 64 | |
35 | ||
bb2d1ea5 SK |
36 | static int is_iso(int fd) |
37 | { | |
38 | char label[8]; | |
1da83869 | 39 | |
bb2d1ea5 SK |
40 | if (pread(fd, &label, 8, 0x8000) == -1) |
41 | return 1; | |
42 | return memcmp(&label, &"\1CD001\1", 8); | |
43 | } | |
44 | ||
6f81751a SK |
45 | static int isonum_721(unsigned char *p) |
46 | { | |
47 | return ((p[0] & 0xff) | |
48 | | ((p[1] & 0xff) << 8)); | |
66ee8158 KZ |
49 | } |
50 | ||
6f81751a SK |
51 | static int isonum_722(unsigned char *p) |
52 | { | |
53 | return ((p[1] & 0xff) | |
54 | | ((p[0] & 0xff) << 8)); | |
66ee8158 KZ |
55 | } |
56 | ||
6f81751a SK |
57 | static int isonum_723(unsigned char *p, int xflag) |
58 | { | |
59 | int le = isonum_721(p); | |
60 | int be = isonum_722(p + 2); | |
1da83869 | 61 | |
6f81751a | 62 | if (xflag && le != be) |
66ee8158 | 63 | /* translation is useless */ |
6f81751a SK |
64 | warnx("723error: le=%d be=%d", le, be); |
65 | return (le); | |
66ee8158 KZ |
66 | } |
67 | ||
6f81751a SK |
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)); | |
66ee8158 KZ |
74 | } |
75 | ||
6f81751a SK |
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)); | |
66ee8158 KZ |
82 | } |
83 | ||
6f81751a SK |
84 | static int isonum_733(unsigned char *p, int xflag) |
85 | { | |
86 | int le = isonum_731(p); | |
87 | int be = isonum_732(p + 4); | |
1da83869 | 88 | |
6f81751a SK |
89 | if (xflag && le != be) |
90 | /* translation is useless */ | |
5a2ed453 | 91 | warnx("733error: le=%d be=%d", le, be); |
6f81751a | 92 | return (le); |
66ee8158 KZ |
93 | } |
94 | ||
c3801802 | 95 | static int isosize(int argc, char *filenamep, int xflag, long divisor) |
6f81751a | 96 | { |
c3801802 | 97 | int fd, nsecs, ssize, rc = -1; |
e3e0054f SK |
98 | unsigned char volume_space_size[8]; |
99 | unsigned char logical_block_size[4]; | |
66ee8158 | 100 | |
c3801802 KZ |
101 | if ((fd = open(filenamep, O_RDONLY)) < 0) { |
102 | warn(_("cannot open %s"), filenamep); | |
103 | goto done; | |
104 | } | |
bb2d1ea5 | 105 | if (is_iso(fd)) |
b548a8c9 | 106 | warnx(_("%s: might not be an ISO filesystem"), filenamep); |
73611843 | 107 | |
c3801802 KZ |
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)) { | |
e3e0054f | 110 | if (errno) |
c3801802 KZ |
111 | warn(_("read error on %s"), filenamep); |
112 | else | |
113 | warnx(_("read error on %s"), filenamep); | |
114 | goto done; | |
e3e0054f | 115 | } |
66ee8158 | 116 | |
e3e0054f | 117 | nsecs = isonum_733(volume_space_size, xflag); |
6f81751a | 118 | /* isonum_723 returns nowadays always 2048 */ |
e3e0054f | 119 | ssize = isonum_723(logical_block_size, xflag); |
66ee8158 | 120 | |
799e5842 SK |
121 | if (1 < argc) |
122 | printf("%s: ", filenamep); | |
1da83869 | 123 | if (xflag) |
6f81751a | 124 | printf(_("sector count: %d, sector size: %d\n"), nsecs, ssize); |
1da83869 | 125 | else { |
66ee8158 KZ |
126 | long long product = nsecs; |
127 | ||
128 | if (divisor == 0) | |
6f81751a | 129 | printf("%lld\n", product * ssize); |
66ee8158 | 130 | else if (divisor == ssize) |
6f81751a | 131 | printf("%d\n", nsecs); |
66ee8158 | 132 | else |
6f81751a | 133 | printf("%lld\n", (product * ssize) / divisor); |
66ee8158 | 134 | } |
122db55d | 135 | |
c3801802 KZ |
136 | rc = 0; |
137 | done: | |
138 | if (fd >= 0) | |
139 | close(fd); | |
140 | return rc; | |
66ee8158 KZ |
141 | } |
142 | ||
6e1eda6f | 143 | static void __attribute__((__noreturn__)) usage(void) |
9404cc7f | 144 | { |
1da83869 KZ |
145 | |
146 | fputs(USAGE_HEADER, stdout); | |
147 | fprintf(stdout, | |
148 | _(" %s [options] <iso9660_image_file> ...\n"), | |
9404cc7f | 149 | program_invocation_short_name); |
451dbcfa | 150 | |
1da83869 KZ |
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); | |
451dbcfa | 157 | |
f45f3ec3 RM |
158 | printf(USAGE_HELP_OPTIONS(25)); |
159 | printf(USAGE_MAN_TAIL("isosize(8)")); | |
4eba43a7 | 160 | |
6e1eda6f | 161 | exit(EXIT_SUCCESS); |
9404cc7f FC |
162 | } |
163 | ||
6f81751a SK |
164 | int main(int argc, char **argv) |
165 | { | |
c3801802 | 166 | int j, ct_err = 0, ct, opt, xflag = 0; |
ab3a34ff | 167 | long divisor = 0; |
66ee8158 | 168 | |
4eba43a7 | 169 | static const struct option longopts[] = { |
87918040 SK |
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} | |
4eba43a7 SK |
175 | }; |
176 | ||
66ee8158 KZ |
177 | setlocale(LC_ALL, ""); |
178 | bindtextdomain(PACKAGE, LOCALEDIR); | |
179 | textdomain(PACKAGE); | |
2c308875 | 180 | close_stdout_atexit(); |
66ee8158 | 181 | |
1da83869 | 182 | while ((opt = getopt_long(argc, argv, "d:xVh", longopts, NULL)) != -1) { |
66ee8158 KZ |
183 | switch (opt) { |
184 | case 'd': | |
ab3a34ff SK |
185 | divisor = |
186 | strtol_or_err(optarg, | |
187 | _("invalid divisor argument")); | |
66ee8158 KZ |
188 | break; |
189 | case 'x': | |
190 | xflag = 1; | |
191 | break; | |
4eba43a7 | 192 | case 'V': |
2c308875 | 193 | print_version(EXIT_SUCCESS); |
4eba43a7 | 194 | case 'h': |
6e1eda6f | 195 | usage(); |
66ee8158 | 196 | default: |
677ec86c | 197 | errtryhelp(EXIT_FAILURE); |
66ee8158 | 198 | } |
1da83869 | 199 | } |
66ee8158 KZ |
200 | |
201 | ct = argc - optind; | |
202 | ||
6e1eda6f RM |
203 | if (ct <= 0) { |
204 | warnx(_("no device specified")); | |
205 | errtryhelp(EXIT_FAILURE); | |
206 | } | |
66ee8158 | 207 | |
c3801802 KZ |
208 | for (j = optind; j < argc; j++) { |
209 | if (isosize(ct, argv[j], xflag, divisor) != 0) | |
210 | ct_err++; | |
211 | } | |
66ee8158 | 212 | |
c3801802 KZ |
213 | return ct == ct_err ? ISOSIZE_EXIT_ALLFAILED : /* all failed */ |
214 | ct_err ? ISOSIZE_EXIT_SOMEOK : /* some ok */ | |
215 | EXIT_SUCCESS; /* all success */ | |
66ee8158 | 216 | } |