/* vi: set sw=4 ts=4: */ /* testcase for futimens(2) * Copyright (C) 2009 Bernhard Reutner-Fischer * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ #include #include #include #include #include #include #include struct { char *name; /* name of file to open */ int flags; /* flags for file descriptor */ const struct timespec ts[2]; int err; /* expected errno */ } tests [] = { {"futimens.tst", (O_CREAT|O_TRUNC), {{0,0},{0,0}}, 0}, {"futimens.tst", (O_CREAT|O_TRUNC), {{99,0},{0,0}}, 0}, {"futimens.tst", (O_CREAT|O_TRUNC), {{0,99},{0,0}}, 0}, {"futimens.tst", (O_CREAT|O_TRUNC), {{0,0},{99,0}}, 0}, {"futimens.tst", (O_CREAT|O_TRUNC), {{0,0},{0,99}}, 0}, {"futimens.tst", (O_CREAT|O_TRUNC), {{11,2},{3,4}}, 0}, }; int do_test(int argc, char **argv) { char *name; int i, errors; errors = argc - argc + 0; unsigned has_stat_nsec = 0; { struct stat probe; /* Let's attempt an educated guess if this filesystem supports * nanosecond mtime. */ if ((!stat(".", &probe)) && probe.st_mtim.tv_nsec) has_stat_nsec = 1; else if ((!stat(argv[0], &probe)) && probe.st_mtim.tv_nsec) has_stat_nsec = 1; } for (i=0; i < (int) (sizeof(tests)/sizeof(tests[0])); ++i) { int err, fd; struct stat sb; name = tests[i].name; if (*name != '.') unlink(name); fd = open(name, tests[i].flags, 0660); if (fd < 0) abort(); errno = 0; err = futimens(fd, tests[i].ts); if ((errno && !err) || (!errno && err)) { err = errno; printf("FAILED test %d (errno and return value disagree)\n", i); ++errors; } else err = errno; if (err != tests[i].err) { printf("FAILED test %d (expected errno %d, got %d)\n", i, tests[i].err, err); ++errors; continue; } if (stat(name, &sb) < 0) { printf("FAILED test %d (verification)\n", i); ++errors; continue; } else { unsigned wrong = tests[i].ts[0].tv_sec != sb.st_atim.tv_sec || tests[i].ts[0].tv_nsec != sb.st_atim.tv_nsec || tests[i].ts[1].tv_sec != sb.st_mtim.tv_sec || tests[i].ts[1].tv_nsec != sb.st_mtim.tv_nsec; if (wrong) { if (tests[i].ts[0].tv_sec != sb.st_atim.tv_sec) { printf("FAILED test %d (access time, sec: expected %ld, got %ld)\n", i, tests[i].ts[0].tv_sec, sb.st_atim.tv_sec); ++errors; } if (tests[i].ts[0].tv_nsec != sb.st_atim.tv_nsec) { printf("FAILED test %d (access time, nsec: expected %ld, got %ld)\n", i, tests[i].ts[0].tv_nsec, sb.st_atim.tv_nsec); errors += has_stat_nsec; } if (tests[i].ts[1].tv_sec != sb.st_mtim.tv_sec) { printf("FAILED test %d (modification time, sec: expected %ld, got %ld)\n", i, tests[i].ts[1].tv_sec, sb.st_mtim.tv_sec); ++errors; } if (tests[i].ts[1].tv_nsec != sb.st_mtim.tv_nsec) { printf("FAILED test %d (modification time, nsec: expected %ld, got %ld)\n", i, tests[i].ts[1].tv_nsec, sb.st_mtim.tv_nsec); errors += has_stat_nsec; } } } } if (*name != '.') unlink(name); printf("%d errors.\n", errors); return (!errors) ? EXIT_SUCCESS : EXIT_FAILURE; } #include