2 * isosize.c - Andries Brouwer, 000608
4 * use header info to find size of iso9660 file system
5 * output a number - useful in scripts
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
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]
31 #include "closestream.h"
33 #define ISOSIZE_EXIT_ALLFAILED 32
34 #define ISOSIZE_EXIT_SOMEOK 64
36 static int is_iso(int fd
)
40 if (pread(fd
, &label
, 8, 0x8000) == -1)
42 return memcmp(&label
, &"\1CD001\1", 8);
45 static int isonum_721(unsigned char *p
)
48 | ((p
[1] & 0xff) << 8));
51 static int isonum_722(unsigned char *p
)
54 | ((p
[0] & 0xff) << 8));
57 static int isonum_723(unsigned char *p
, int xflag
)
59 int le
= isonum_721(p
);
60 int be
= isonum_722(p
+ 2);
62 if (xflag
&& le
!= be
)
63 /* translation is useless */
64 warnx("723error: le=%d be=%d", le
, be
);
68 static int isonum_731(unsigned char *p
)
71 | ((p
[1] & 0xff) << 8)
72 | ((p
[2] & 0xff) << 16)
73 | ((p
[3] & 0xff) << 24));
76 static int isonum_732(unsigned char *p
)
79 | ((p
[2] & 0xff) << 8)
80 | ((p
[1] & 0xff) << 16)
81 | ((p
[0] & 0xff) << 24));
84 static int isonum_733(unsigned char *p
, int xflag
)
86 int le
= isonum_731(p
);
87 int be
= isonum_732(p
+ 4);
89 if (xflag
&& le
!= be
)
90 /* translation is useless */
91 warnx("733error: le=%d be=%d", le
, be
);
95 static int isosize(int argc
, char *filenamep
, int xflag
, long divisor
)
97 int fd
, nsecs
, ssize
, rc
= -1;
98 unsigned char volume_space_size
[8];
99 unsigned char logical_block_size
[4];
101 if ((fd
= open(filenamep
, O_RDONLY
)) < 0) {
102 warn(_("cannot open %s"), filenamep
);
106 warnx(_("%s: might not be an ISO filesystem"), filenamep
);
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
)) {
111 warn(_("read error on %s"), filenamep
);
113 warnx(_("read error on %s"), filenamep
);
117 nsecs
= isonum_733(volume_space_size
, xflag
);
118 /* isonum_723 returns nowadays always 2048 */
119 ssize
= isonum_723(logical_block_size
, xflag
);
122 printf("%s: ", filenamep
);
124 printf(_("sector count: %d, sector size: %d\n"), nsecs
, ssize
);
126 long long product
= nsecs
;
129 printf("%lld\n", product
* ssize
);
130 else if (divisor
== ssize
)
131 printf("%d\n", nsecs
);
133 printf("%lld\n", (product
* ssize
) / divisor
);
143 static void __attribute__((__noreturn__
)) usage(void)
146 fputs(USAGE_HEADER
, stdout
);
148 _(" %s [options] <iso9660_image_file> ...\n"),
149 program_invocation_short_name
);
151 fputs(USAGE_SEPARATOR
, stdout
);
152 fputs(_("Show the length of an ISO-9660 filesystem.\n"), stdout
);
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
);
158 printf(USAGE_HELP_OPTIONS(25));
159 printf(USAGE_MAN_TAIL("isosize(8)"));
164 int main(int argc
, char **argv
)
166 int j
, ct_err
= 0, ct
, opt
, xflag
= 0;
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'},
177 setlocale(LC_ALL
, "");
178 bindtextdomain(PACKAGE
, LOCALEDIR
);
180 close_stdout_atexit();
182 while ((opt
= getopt_long(argc
, argv
, "d:xVh", longopts
, NULL
)) != -1) {
186 strtol_or_err(optarg
,
187 _("invalid divisor argument"));
193 print_version(EXIT_SUCCESS
);
197 errtryhelp(EXIT_FAILURE
);
204 warnx(_("no device specified"));
205 errtryhelp(EXIT_FAILURE
);
208 for (j
= optind
; j
< argc
; j
++) {
209 if (isosize(ct
, argv
[j
], xflag
, divisor
) != 0)
213 return ct
== ct_err
? ISOSIZE_EXIT_ALLFAILED
: /* all failed */
214 ct_err
? ISOSIZE_EXIT_SOMEOK
: /* some ok */
215 EXIT_SUCCESS
; /* all success */