]> git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/fadvise.c
Merge branch 'sed' of https://github.com/t-8ch/util-linux
[thirdparty/util-linux.git] / misc-utils / fadvise.c
1 /*
2 * fadvise - utility to use the posix_fadvise(2)
3 *
4 * Copyright (C) 2022 Red Hat, Inc. All rights reserved.
5 * Written by Masatake YAMATO <yamato@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it would be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include <fcntl.h>
23 #include <getopt.h>
24 #include <stdbool.h>
25 #include <stdio.h>
26
27 #include "c.h"
28 #include "nls.h"
29 #include "strutils.h"
30
31 static const struct advice {
32 const char *name;
33 int num;
34 } advices [] = {
35 { "normal", POSIX_FADV_NORMAL, },
36 { "sequential", POSIX_FADV_SEQUENTIAL, },
37 { "random", POSIX_FADV_RANDOM, },
38 { "noreuse", POSIX_FADV_NOREUSE, },
39 { "willneeded", POSIX_FADV_WILLNEED, },
40 { "dontneed", POSIX_FADV_DONTNEED, },
41 };
42
43 static void __attribute__((__noreturn__)) usage(void)
44 {
45 FILE *out = stdout;
46 size_t i;
47
48 fputs(USAGE_HEADER, out);
49 fprintf(out, _(" %s [options] file\n"), program_invocation_short_name);
50 fprintf(out, _(" %s [options] --fd|-d file-descriptor\n"), program_invocation_short_name);
51
52 fputs(USAGE_OPTIONS, out);
53 fputs(_(" -a, --advice <advice> applying advice to the file (default: \"dontneed\")\n"), out);
54 fputs(_(" -l, --length <num> length for range operations, in bytes\n"), out);
55 fputs(_(" -o, --offset <num> offset for range operations, in bytes\n"), out);
56
57 fputs(USAGE_SEPARATOR, out);
58 fprintf(out, USAGE_HELP_OPTIONS(23));
59
60 fputs(_("\nAvailable values for advice:\n"), out);
61 for (i = 0; i < ARRAY_SIZE(advices); i++) {
62 fprintf(out, " %s\n",
63 advices[i].name);
64 }
65
66 fprintf(out, USAGE_MAN_TAIL("fadvise(1)"));
67
68 exit(EXIT_SUCCESS);
69 }
70
71 int main(int argc, char ** argv)
72 {
73 int c;
74 int rc;
75 bool do_close = false;
76
77 int fd = -1;
78 off_t offset = 0;
79 off_t len = 0;
80 int advice = POSIX_FADV_DONTNEED;
81
82 static const struct option longopts[] = {
83 { "advice", required_argument, NULL, 'a' },
84 { "fd", required_argument, NULL, 'd' },
85 { "length", required_argument, NULL, 'l' },
86 { "offset", required_argument, NULL, 'o' },
87 { "version", no_argument, NULL, 'V' },
88 { "help", no_argument, NULL, 'h' },
89 { NULL, 0, NULL, 0 },
90 };
91
92 setlocale(LC_ALL, "");
93 bindtextdomain(PACKAGE, LOCALEDIR);
94 textdomain(PACKAGE);
95
96 while ((c = getopt_long (argc, argv, "a:d:hl:o:V", longopts, NULL)) != -1) {
97 switch (c) {
98 case 'a':
99 advice = -1;
100 for (size_t i = 0; i < ARRAY_SIZE(advices); i++) {
101 if (strcmp(optarg, advices[i].name) == 0) {
102 advice = advices[i].num;
103 break;
104 }
105 }
106 if (advice == -1)
107 errx(EXIT_FAILURE, "invalid advice argument: '%s'", optarg);
108 break;
109 case 'd':
110 fd = strtos32_or_err(optarg,
111 _("invalid fd argument"));
112 break;
113 case 'l':
114 len = strtosize_or_err(optarg,
115 _("invalid length argument"));
116 break;
117 case 'o':
118 offset = strtosize_or_err(optarg,
119 _("invalid offset argument"));
120 break;
121 case 'V':
122 print_version(EXIT_SUCCESS);
123 case 'h':
124 usage();
125 default:
126 errtryhelp(EXIT_FAILURE);
127 }
128 }
129
130 if (optind == argc && fd == -1) {
131 warnx(_("no file specified"));
132 errtryhelp(EXIT_FAILURE);
133 }
134
135 if (argc - optind > 0 && fd != -1) {
136 warnx(_("specify either file descriptor or file name"));
137 errtryhelp(EXIT_FAILURE);
138 }
139
140 if (argc - optind > 1) {
141 warnx(_("specify one file descriptor or file name"));
142 errtryhelp(EXIT_FAILURE);
143 }
144
145 if (fd == -1) {
146 fd = open(argv[optind], O_RDONLY);
147 if (fd < 0)
148 err(EXIT_FAILURE, _("cannot open %s"), argv[optind]);
149 do_close = true;
150 }
151
152 rc = posix_fadvise(fd,
153 offset, len,
154 advice);
155 if (rc != 0)
156 warnx(_("failed to advise: %s"), strerror(rc));
157
158 if (do_close)
159 close(fd);
160
161 return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
162 }