]> git.ipfire.org Git - thirdparty/util-linux.git/blame - disk-utils/isosize.c
disk-utils: add SPDX and Copyright notices
[thirdparty/util-linux.git] / disk-utils / isosize.c
CommitLineData
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
44static 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 53static 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;
95done:
96 if (fd >= 0)
97 close(fd);
98 return rc;
66ee8158
KZ
99}
100
6e1eda6f 101static 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
122int 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}