]>
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 | |
bb2d1ea5 SK |
33 | static int is_iso(int fd) |
34 | { | |
35 | char label[8]; | |
36 | if (pread(fd, &label, 8, 0x8000) == -1) | |
37 | return 1; | |
38 | return memcmp(&label, &"\1CD001\1", 8); | |
39 | } | |
40 | ||
6f81751a SK |
41 | static int isonum_721(unsigned char *p) |
42 | { | |
43 | return ((p[0] & 0xff) | |
44 | | ((p[1] & 0xff) << 8)); | |
66ee8158 KZ |
45 | } |
46 | ||
6f81751a SK |
47 | static int isonum_722(unsigned char *p) |
48 | { | |
49 | return ((p[1] & 0xff) | |
50 | | ((p[0] & 0xff) << 8)); | |
66ee8158 KZ |
51 | } |
52 | ||
6f81751a SK |
53 | static int isonum_723(unsigned char *p, int xflag) |
54 | { | |
55 | int le = isonum_721(p); | |
56 | int be = isonum_722(p + 2); | |
57 | if (xflag && le != be) | |
66ee8158 | 58 | /* translation is useless */ |
6f81751a SK |
59 | warnx("723error: le=%d be=%d", le, be); |
60 | return (le); | |
66ee8158 KZ |
61 | } |
62 | ||
6f81751a SK |
63 | static int isonum_731(unsigned char *p) |
64 | { | |
65 | return ((p[0] & 0xff) | |
66 | | ((p[1] & 0xff) << 8) | |
67 | | ((p[2] & 0xff) << 16) | |
68 | | ((p[3] & 0xff) << 24)); | |
66ee8158 KZ |
69 | } |
70 | ||
6f81751a SK |
71 | static int isonum_732(unsigned char *p) |
72 | { | |
73 | return ((p[3] & 0xff) | |
74 | | ((p[2] & 0xff) << 8) | |
75 | | ((p[1] & 0xff) << 16) | |
76 | | ((p[0] & 0xff) << 24)); | |
66ee8158 KZ |
77 | } |
78 | ||
6f81751a SK |
79 | static int isonum_733(unsigned char *p, int xflag) |
80 | { | |
81 | int le = isonum_731(p); | |
82 | int be = isonum_732(p + 4); | |
83 | if (xflag && le != be) | |
84 | /* translation is useless */ | |
5a2ed453 | 85 | warnx("733error: le=%d be=%d", le, be); |
6f81751a | 86 | return (le); |
66ee8158 KZ |
87 | } |
88 | ||
799e5842 | 89 | static void isosize(int argc, char *filenamep, int xflag, long divisor) |
6f81751a | 90 | { |
66ee8158 | 91 | int fd, nsecs, ssize; |
e3e0054f SK |
92 | unsigned char volume_space_size[8]; |
93 | unsigned char logical_block_size[4]; | |
66ee8158 | 94 | |
73611843 | 95 | if ((fd = open(filenamep, O_RDONLY)) < 0) |
289dcc90 | 96 | err(EXIT_FAILURE, _("cannot open %s"), filenamep); |
bb2d1ea5 | 97 | if (is_iso(fd)) |
b548a8c9 | 98 | warnx(_("%s: might not be an ISO filesystem"), filenamep); |
73611843 | 99 | |
e3e0054f SK |
100 | if (pread(fd, volume_space_size, sizeof(volume_space_size), 0x8050) <= 0 || |
101 | pread(fd, logical_block_size, sizeof(logical_block_size), 0x8080) <= 0) { | |
102 | if (errno) | |
103 | err(EXIT_FAILURE, _("read error on %s"), filenamep); | |
104 | errx(EXIT_FAILURE, _("read error on %s"), filenamep); | |
105 | } | |
66ee8158 | 106 | |
e3e0054f | 107 | nsecs = isonum_733(volume_space_size, xflag); |
6f81751a | 108 | /* isonum_723 returns nowadays always 2048 */ |
e3e0054f | 109 | ssize = isonum_723(logical_block_size, xflag); |
66ee8158 | 110 | |
799e5842 SK |
111 | if (1 < argc) |
112 | printf("%s: ", filenamep); | |
66ee8158 | 113 | if (xflag) { |
6f81751a | 114 | printf(_("sector count: %d, sector size: %d\n"), nsecs, ssize); |
66ee8158 KZ |
115 | } else { |
116 | long long product = nsecs; | |
117 | ||
118 | if (divisor == 0) | |
6f81751a | 119 | printf("%lld\n", product * ssize); |
66ee8158 | 120 | else if (divisor == ssize) |
6f81751a | 121 | printf("%d\n", nsecs); |
66ee8158 | 122 | else |
6f81751a | 123 | printf("%lld\n", (product * ssize) / divisor); |
66ee8158 | 124 | } |
122db55d | 125 | |
126 | close(fd); | |
66ee8158 KZ |
127 | } |
128 | ||
6e1eda6f | 129 | static void __attribute__((__noreturn__)) usage(void) |
9404cc7f | 130 | { |
6e1eda6f | 131 | FILE *out = stdout; |
bb7ea8d8 SK |
132 | fputs(USAGE_HEADER, out); |
133 | fprintf(out, | |
b548a8c9 | 134 | _(" %s [options] <iso9660_image_file>\n"), |
9404cc7f | 135 | program_invocation_short_name); |
451dbcfa BS |
136 | |
137 | fputs(USAGE_SEPARATOR, out); | |
138 | fputs(_("Show the length of an ISO-9660 filesystem.\n"), out); | |
139 | ||
bb7ea8d8 | 140 | fputs(USAGE_OPTIONS, out); |
b548a8c9 BS |
141 | fputs(_(" -d, --divisor=<number> divide the amount of bytes by <number>\n"), out); |
142 | fputs(_(" -x, --sectors show sector count and size\n"), out); | |
bb7ea8d8 SK |
143 | fputs(USAGE_SEPARATOR, out); |
144 | fputs(USAGE_HELP, out); | |
145 | fputs(USAGE_VERSION, out); | |
146 | fprintf(out, USAGE_MAN_TAIL("isosize(8)")); | |
4eba43a7 | 147 | |
6e1eda6f | 148 | exit(EXIT_SUCCESS); |
9404cc7f FC |
149 | } |
150 | ||
6f81751a SK |
151 | int main(int argc, char **argv) |
152 | { | |
4eba43a7 | 153 | int j, ct, opt, xflag = 0; |
ab3a34ff | 154 | long divisor = 0; |
66ee8158 | 155 | |
4eba43a7 | 156 | static const struct option longopts[] = { |
87918040 SK |
157 | {"divisor", required_argument, NULL, 'd'}, |
158 | {"sectors", no_argument, NULL, 'x'}, | |
159 | {"version", no_argument, NULL, 'V'}, | |
160 | {"help", no_argument, NULL, 'h'}, | |
161 | {NULL, 0, NULL, 0} | |
4eba43a7 SK |
162 | }; |
163 | ||
66ee8158 KZ |
164 | setlocale(LC_ALL, ""); |
165 | bindtextdomain(PACKAGE, LOCALEDIR); | |
166 | textdomain(PACKAGE); | |
45ca68ec | 167 | atexit(close_stdout); |
66ee8158 | 168 | |
4eba43a7 | 169 | while ((opt = getopt_long(argc, argv, "d:xVh", longopts, NULL)) != -1) |
66ee8158 KZ |
170 | switch (opt) { |
171 | case 'd': | |
ab3a34ff SK |
172 | divisor = |
173 | strtol_or_err(optarg, | |
174 | _("invalid divisor argument")); | |
66ee8158 KZ |
175 | break; |
176 | case 'x': | |
177 | xflag = 1; | |
178 | break; | |
4eba43a7 | 179 | case 'V': |
bb7ea8d8 | 180 | printf(UTIL_LINUX_VERSION); |
4eba43a7 SK |
181 | return EXIT_SUCCESS; |
182 | case 'h': | |
6e1eda6f | 183 | usage(); |
66ee8158 | 184 | default: |
677ec86c | 185 | errtryhelp(EXIT_FAILURE); |
66ee8158 | 186 | } |
66ee8158 KZ |
187 | |
188 | ct = argc - optind; | |
189 | ||
6e1eda6f RM |
190 | if (ct <= 0) { |
191 | warnx(_("no device specified")); | |
192 | errtryhelp(EXIT_FAILURE); | |
193 | } | |
66ee8158 | 194 | |
799e5842 SK |
195 | for (j = optind; j < argc; j++) |
196 | isosize(ct, argv[j], xflag, divisor); | |
66ee8158 | 197 | |
6f81751a | 198 | return EXIT_SUCCESS; |
66ee8158 | 199 | } |