]>
Commit | Line | Data |
---|---|---|
66ee8158 | 1 | /* |
9e95aa12 KZ |
2 | * SPDX-License-Identifier: GPL-2.0-or-later |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * Copyright (C) 2000 Andries Brouwer | |
10 | * Copyright (C) 2023 Karel Zak <kzak@redhat.com> | |
66ee8158 KZ |
11 | * |
12 | * use header info to find size of iso9660 file system | |
13 | * output a number - useful in scripts | |
14 | * | |
15 | * Synopsis: | |
16 | * isosize [-x] [-d <num>] <filename> | |
17 | * where "-x" gives length in sectors and sector size while | |
18 | * without this argument the size is given in bytes | |
19 | * without "-x" gives length in bytes unless "-d <num>" is | |
20 | * given. In the latter case the length in bytes divided | |
21 | * by <num> is given | |
22 | * | |
23 | * Version 2.03 2000/12/21 | |
24 | * - add "-d <num>" option and use long long to fix things > 2 GB | |
25 | * Version 2.02 2000/10/11 | |
26 | * - error messages on IO failures [D. Gilbert] | |
66ee8158 KZ |
27 | */ |
28 | #include <stdio.h> | |
29 | #include <stdlib.h> | |
30 | #include <getopt.h> | |
31 | #include <fcntl.h> | |
32 | #include <unistd.h> | |
4c0ecdd4 | 33 | #include <errno.h> |
66ee8158 KZ |
34 | |
35 | #include "nls.h" | |
73611843 | 36 | #include "c.h" |
ab3a34ff | 37 | #include "strutils.h" |
45ca68ec | 38 | #include "closestream.h" |
1f10f4af | 39 | #include "iso9660.h" |
66ee8158 | 40 | |
c3801802 KZ |
41 | #define ISOSIZE_EXIT_ALLFAILED 32 |
42 | #define ISOSIZE_EXIT_SOMEOK 64 | |
43 | ||
bb2d1ea5 SK |
44 | static int is_iso(int fd) |
45 | { | |
46 | char label[8]; | |
1da83869 | 47 | |
bb2d1ea5 SK |
48 | if (pread(fd, &label, 8, 0x8000) == -1) |
49 | return 1; | |
50 | return memcmp(&label, &"\1CD001\1", 8); | |
51 | } | |
52 | ||
c3801802 | 53 | static int isosize(int argc, char *filenamep, int xflag, long divisor) |
6f81751a | 54 | { |
c3801802 | 55 | int fd, nsecs, ssize, rc = -1; |
e3e0054f SK |
56 | unsigned char volume_space_size[8]; |
57 | unsigned char logical_block_size[4]; | |
66ee8158 | 58 | |
c3801802 KZ |
59 | if ((fd = open(filenamep, O_RDONLY)) < 0) { |
60 | warn(_("cannot open %s"), filenamep); | |
61 | goto done; | |
62 | } | |
bb2d1ea5 | 63 | if (is_iso(fd)) |
b548a8c9 | 64 | warnx(_("%s: might not be an ISO filesystem"), filenamep); |
73611843 | 65 | |
c3801802 KZ |
66 | if (pread(fd, volume_space_size, sizeof(volume_space_size), 0x8050) != sizeof(volume_space_size) || |
67 | pread(fd, logical_block_size, sizeof(logical_block_size), 0x8080) != sizeof(logical_block_size)) { | |
e3e0054f | 68 | if (errno) |
c3801802 KZ |
69 | warn(_("read error on %s"), filenamep); |
70 | else | |
71 | warnx(_("read error on %s"), filenamep); | |
72 | goto done; | |
e3e0054f | 73 | } |
66ee8158 | 74 | |
e3e0054f | 75 | nsecs = isonum_733(volume_space_size, xflag); |
6f81751a | 76 | /* isonum_723 returns nowadays always 2048 */ |
e3e0054f | 77 | ssize = isonum_723(logical_block_size, xflag); |
66ee8158 | 78 | |
799e5842 SK |
79 | if (1 < argc) |
80 | printf("%s: ", filenamep); | |
1da83869 | 81 | if (xflag) |
6f81751a | 82 | printf(_("sector count: %d, sector size: %d\n"), nsecs, ssize); |
1da83869 | 83 | else { |
66ee8158 KZ |
84 | long long product = nsecs; |
85 | ||
86 | if (divisor == 0) | |
6f81751a | 87 | printf("%lld\n", product * ssize); |
66ee8158 | 88 | else if (divisor == ssize) |
6f81751a | 89 | printf("%d\n", nsecs); |
66ee8158 | 90 | else |
6f81751a | 91 | printf("%lld\n", (product * ssize) / divisor); |
66ee8158 | 92 | } |
122db55d | 93 | |
c3801802 KZ |
94 | rc = 0; |
95 | done: | |
96 | if (fd >= 0) | |
97 | close(fd); | |
98 | return rc; | |
66ee8158 KZ |
99 | } |
100 | ||
6e1eda6f | 101 | static void __attribute__((__noreturn__)) usage(void) |
9404cc7f | 102 | { |
1da83869 KZ |
103 | |
104 | fputs(USAGE_HEADER, stdout); | |
105 | fprintf(stdout, | |
106 | _(" %s [options] <iso9660_image_file> ...\n"), | |
9404cc7f | 107 | program_invocation_short_name); |
451dbcfa | 108 | |
1da83869 KZ |
109 | fputs(USAGE_SEPARATOR, stdout); |
110 | fputs(_("Show the length of an ISO-9660 filesystem.\n"), stdout); | |
111 | ||
112 | fputs(USAGE_OPTIONS, stdout); | |
113 | fputs(_(" -d, --divisor=<number> divide the amount of bytes by <number>\n"), stdout); | |
114 | fputs(_(" -x, --sectors show sector count and size\n"), stdout); | |
451dbcfa | 115 | |
bad4c729 MY |
116 | fprintf(stdout, USAGE_HELP_OPTIONS(25)); |
117 | fprintf(stdout, USAGE_MAN_TAIL("isosize(8)")); | |
4eba43a7 | 118 | |
6e1eda6f | 119 | exit(EXIT_SUCCESS); |
9404cc7f FC |
120 | } |
121 | ||
6f81751a SK |
122 | int main(int argc, char **argv) |
123 | { | |
c3801802 | 124 | int j, ct_err = 0, ct, opt, xflag = 0; |
ab3a34ff | 125 | long divisor = 0; |
66ee8158 | 126 | |
4eba43a7 | 127 | static const struct option longopts[] = { |
87918040 SK |
128 | {"divisor", required_argument, NULL, 'd'}, |
129 | {"sectors", no_argument, NULL, 'x'}, | |
130 | {"version", no_argument, NULL, 'V'}, | |
131 | {"help", no_argument, NULL, 'h'}, | |
132 | {NULL, 0, NULL, 0} | |
4eba43a7 SK |
133 | }; |
134 | ||
66ee8158 KZ |
135 | setlocale(LC_ALL, ""); |
136 | bindtextdomain(PACKAGE, LOCALEDIR); | |
137 | textdomain(PACKAGE); | |
2c308875 | 138 | close_stdout_atexit(); |
66ee8158 | 139 | |
1da83869 | 140 | while ((opt = getopt_long(argc, argv, "d:xVh", longopts, NULL)) != -1) { |
66ee8158 KZ |
141 | switch (opt) { |
142 | case 'd': | |
ab3a34ff SK |
143 | divisor = |
144 | strtol_or_err(optarg, | |
145 | _("invalid divisor argument")); | |
66ee8158 KZ |
146 | break; |
147 | case 'x': | |
148 | xflag = 1; | |
149 | break; | |
4eba43a7 | 150 | case 'V': |
2c308875 | 151 | print_version(EXIT_SUCCESS); |
4eba43a7 | 152 | case 'h': |
6e1eda6f | 153 | usage(); |
66ee8158 | 154 | default: |
677ec86c | 155 | errtryhelp(EXIT_FAILURE); |
66ee8158 | 156 | } |
1da83869 | 157 | } |
66ee8158 KZ |
158 | |
159 | ct = argc - optind; | |
160 | ||
6e1eda6f RM |
161 | if (ct <= 0) { |
162 | warnx(_("no device specified")); | |
163 | errtryhelp(EXIT_FAILURE); | |
164 | } | |
66ee8158 | 165 | |
c3801802 KZ |
166 | for (j = optind; j < argc; j++) { |
167 | if (isosize(ct, argv[j], xflag, divisor) != 0) | |
168 | ct_err++; | |
169 | } | |
66ee8158 | 170 | |
c3801802 KZ |
171 | return ct == ct_err ? ISOSIZE_EXIT_ALLFAILED : /* all failed */ |
172 | ct_err ? ISOSIZE_EXIT_SOMEOK : /* some ok */ | |
173 | EXIT_SUCCESS; /* all success */ | |
66ee8158 | 174 | } |