about summary refs log tree commit homepage
path: root/fadvise.c
diff options
context:
space:
mode:
Diffstat (limited to 'fadvise.c')
-rw-r--r--fadvise.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/fadvise.c b/fadvise.c
new file mode 100644
index 0000000..c2392f4
--- /dev/null
+++ b/fadvise.c
@@ -0,0 +1,102 @@
+#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 void apply_fadvise(const char *path, off_t offset, off_t len, int advice)
+{
+        int fd;
+
+        if ((fd = open(path, O_RDONLY)) < 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:")) != -1) {
+                int i;
+                char *err;
+
+                argi += 2;
+                switch(opt) {
+                case 'o':
+                        offset = strtol(optarg, &err, 10);
+                        if (*err || offset < 0) {
+                                fprintf(stderr, "offset must be >= 0\n");
+                                return 1;
+                        }
+                        break;
+                case 'l':
+                        len = strtol(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:
+                        fprintf(stderr,
+                                "Usage: %s [-a advice] [-o offset] "
+                                "[-l length] <files>\n", argv[0]);
+                        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;
+                }
+        }
+
+        for (; argi < argc; ++argi)
+                apply_fadvise(argv[argi], offset, len, advice);
+        return 0;
+}