(root)/
util-linux-2.39/
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  	printf(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  	printf(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  }