pcu.git  about / heads / tags
page cache utilities for Linux
blob 72ef3a3f2c930b59a3643db1fc83d433343c5126 2379 bytes (raw)
$ git show HEAD:fadvise.c	# shows this blob on the CLI

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 
#include "compat-util.h"

static struct fa_advice {
	const char *name;
	const int nr;
} advice_table[] = {
	{ "normal", POSIX_FADV_NORMAL },
	{ "sequential", POSIX_FADV_SEQUENTIAL },
	{ "random", POSIX_FADV_RANDOM },
	{ "noreuse", POSIX_FADV_NOREUSE },
	{ "willneed", POSIX_FADV_WILLNEED },
	{ "dontneed" , POSIX_FADV_DONTNEED }
};

static int usage(const char * argv0)
{
	int i;

	fprintf(stderr,
		"Usage: %s [-a ADVICE] [-o OFFSET] "
		"[-l LENGTH] FILE...\n", argv0);
	fprintf(stderr, "\nPossible values for advice:\n");
	for (i = 0; i < ARRAY_SIZE(advice_table); ++i)
		fprintf(stderr, "\t%s\n", advice_table[i].name);

	return 1;
}

static void apply_fadvise(const char *path, off_t offset, off_t len, int advice)
{
	int fd;

	if ((fd = open_noatime(path) < 0)) {
		fprintf(stderr, "%s: open(): %s\n", path, strerror(errno));
		return;
	}

	if (len <= 0) {
		/* for compatibility with kernels < 2.6.6 */
		struct stat sb;

		if (fstat(fd, &sb) < 0) {
			fprintf(stderr, "%s: fstat(%d): %s\n",
				path, fd, strerror(errno));
			goto out;
		}
		len = sb.st_size;
	}

	if (posix_fadvise(fd, offset, len, advice) < 0)
		fprintf(stderr,
		        "%s: posix_fadvise("
		        "offset=%lu,len=%lu,advice=%d): %s\n",
		        path,
			(unsigned long)offset,
			(unsigned long)len,
			advice, strerror(errno));

out:
	close(fd);
}

int main(int argc, char * const argv[])
{
	off_t offset = 0;
	off_t len = 0;
	int advice = POSIX_FADV_NORMAL;
	int opt;
	int argi = 1;

	while ((opt = getopt(argc, argv, "o:l:a:h")) != -1) {
		int i;
		char *err;

		argi += 2;
		switch(opt) {
		case 'o':
			offset = cstr_to_off_t(optarg, &err, 10);
			if (*err || offset < 0) {
				fprintf(stderr, "offset must be >= 0\n");
				return 1;
			}
			break;
		case 'l':
			len = cstr_to_off_t(optarg, &err, 10);
			if (*err || len < 0) {
				fprintf(stderr, "length must be >= 0\n");
				return 1;
			}
			break;
		case 'a':
			for (i = 0; i < ARRAY_SIZE(advice_table); ++i) {
				if (strcmp(advice_table[i].name, optarg))
					continue;
				advice = advice_table[i].nr;
				break;
			}
			if (i < ARRAY_SIZE(advice_table))
				break;
			fprintf(stderr, "advice '%s' not understood\n", optarg);
			/* fall-through */
		default:
			return usage(argv[0]);
		}
	}

	if (argi >= argc)
		return usage(argv[0]);

	for (; argi < argc; ++argi)
		apply_fadvise(argv[argi], offset, len, advice);
	return 0;
}

git clone https://yhbt.net/pcu.git