aboutsummaryrefslogtreecommitdiff
path: root/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/zfs-tests/tests/functional/ctime/ctime_001_pos.c')
-rw-r--r--tests/zfs-tests/tests/functional/ctime/ctime_001_pos.c347
1 files changed, 347 insertions, 0 deletions
diff --git a/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.c b/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.c
new file mode 100644
index 000000000000..0c0615ff531c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.c
@@ -0,0 +1,347 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <utime.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <strings.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <string.h>
+
+#define ST_ATIME 0
+#define ST_CTIME 1
+#define ST_MTIME 2
+
+#define ALL_MODE (mode_t)(S_IRWXU|S_IRWXG|S_IRWXO)
+
+typedef struct timetest {
+ int type;
+ char *name;
+ int (*func)(const char *pfile);
+} timetest_t;
+
+static char tfile[BUFSIZ] = { 0 };
+
+/*
+ * DESCRIPTION:
+ * Verify time will be changed correctly after each operation.
+ *
+ * STRATEGY:
+ * 1. Define time test array.
+ * 2. Loop through each item in this array.
+ * 3. Verify the time is changed after each operation.
+ *
+ */
+
+static int
+get_file_time(const char *pfile, int what, time_t *ptr)
+{
+ struct stat stat_buf;
+
+ if (pfile == NULL || ptr == NULL) {
+ return (-1);
+ }
+
+ if (stat(pfile, &stat_buf) == -1) {
+ return (-1);
+ }
+
+ switch (what) {
+ case ST_ATIME:
+ *ptr = stat_buf.st_atime;
+ return (0);
+ case ST_CTIME:
+ *ptr = stat_buf.st_ctime;
+ return (0);
+ case ST_MTIME:
+ *ptr = stat_buf.st_mtime;
+ return (0);
+ default:
+ return (-1);
+ }
+}
+
+static int
+do_read(const char *pfile)
+{
+ int fd, ret = 0;
+ char buf[BUFSIZ] = { 0 };
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ if ((fd = open(pfile, O_RDONLY, ALL_MODE)) == -1) {
+ return (-1);
+ }
+ if (read(fd, buf, sizeof (buf)) == -1) {
+ (void) fprintf(stderr, "read(%d, buf, %zd) failed with errno "
+ "%d\n", fd, sizeof (buf), errno);
+ return (1);
+ }
+ (void) close(fd);
+
+ return (ret);
+}
+
+static int
+do_write(const char *pfile)
+{
+ int fd, ret = 0;
+ char buf[BUFSIZ] = "call function do_write()";
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ if ((fd = open(pfile, O_WRONLY, ALL_MODE)) == -1) {
+ return (-1);
+ }
+ if (write(fd, buf, strlen(buf)) == -1) {
+ (void) fprintf(stderr, "write(%d, buf, %d) failed with errno "
+ "%d\n", fd, (int)strlen(buf), errno);
+ return (1);
+ }
+ (void) close(fd);
+
+ return (ret);
+}
+
+static int
+do_link(const char *pfile)
+{
+ int ret = 0;
+ char link_file[BUFSIZ] = { 0 };
+ char *dname;
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ /*
+ * Figure out source file directory name, and create
+ * the link file in the same directory.
+ */
+ dname = dirname((char *)pfile);
+ (void) snprintf(link_file, BUFSIZ, "%s/%s", dname, "link_file");
+
+ if (link(pfile, link_file) == -1) {
+ (void) fprintf(stderr, "link(%s, %s) failed with errno %d\n",
+ pfile, link_file, errno);
+ return (1);
+ }
+
+ (void) unlink(link_file);
+
+ return (ret);
+}
+
+static int
+do_creat(const char *pfile)
+{
+ int fd, ret = 0;
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ if ((fd = creat(pfile, ALL_MODE)) == -1) {
+ (void) fprintf(stderr, "creat(%s, ALL_MODE) failed with errno "
+ "%d\n", pfile, errno);
+ return (1);
+ }
+ (void) close(fd);
+
+ return (ret);
+}
+
+static int
+do_utime(const char *pfile)
+{
+ int ret = 0;
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ /*
+ * Times of the file are set to the current time
+ */
+ if (utime(pfile, NULL) == -1) {
+ (void) fprintf(stderr, "utime(%s, NULL) failed with errno "
+ "%d\n", pfile, errno);
+ return (1);
+ }
+
+ return (ret);
+}
+
+static int
+do_chmod(const char *pfile)
+{
+ int ret = 0;
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ if (chmod(pfile, ALL_MODE) == -1) {
+ (void) fprintf(stderr, "chmod(%s, ALL_MODE) failed with "
+ "errno %d\n", pfile, errno);
+ return (1);
+ }
+
+ return (ret);
+}
+
+static int
+do_chown(const char *pfile)
+{
+ int ret = 0;
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ if (chown(pfile, getuid(), getgid()) == -1) {
+ (void) fprintf(stderr, "chown(%s, %d, %d) failed with errno "
+ "%d\n", pfile, (int)getuid(), (int)getgid(), errno);
+ return (1);
+ }
+
+ return (ret);
+}
+
+static void
+cleanup(void)
+{
+ if ((strlen(tfile) != 0) && (access(tfile, F_OK) == 0)) {
+ (void) unlink(tfile);
+ }
+}
+
+static timetest_t timetest_table[] = {
+ { ST_ATIME, "st_atime", do_read },
+ { ST_ATIME, "st_atime", do_utime },
+ { ST_MTIME, "st_mtime", do_creat },
+ { ST_MTIME, "st_mtime", do_write },
+ { ST_MTIME, "st_mtime", do_utime },
+ { ST_CTIME, "st_ctime", do_creat },
+ { ST_CTIME, "st_ctime", do_write },
+ { ST_CTIME, "st_ctime", do_chmod },
+ { ST_CTIME, "st_ctime", do_chown },
+ { ST_CTIME, "st_ctime", do_link },
+ { ST_CTIME, "st_ctime", do_utime },
+};
+
+#define NCOMMAND (sizeof (timetest_table) / sizeof (timetest_table[0]))
+
+/* ARGSUSED */
+int
+main(int argc, char *argv[])
+{
+ int i, ret, fd;
+ char *penv[] = {"TESTDIR", "TESTFILE0"};
+
+ (void) fprintf(stdout, "Verify [acm]time is modified appropriately.\n");
+ (void) atexit(cleanup);
+
+ /*
+ * Get the environment variable values.
+ */
+ for (i = 0; i < sizeof (penv) / sizeof (char *); i++) {
+ if ((penv[i] = getenv(penv[i])) == NULL) {
+ (void) fprintf(stderr, "getenv(penv[%d])\n", i);
+ return (1);
+ }
+ }
+ (void) snprintf(tfile, sizeof (tfile), "%s/%s", penv[0], penv[1]);
+
+ /*
+ * If the test file is exists, remove it first.
+ */
+ if (access(tfile, F_OK) == 0) {
+ (void) unlink(tfile);
+ }
+ ret = 0;
+ if ((fd = open(tfile, O_WRONLY | O_CREAT | O_TRUNC, ALL_MODE)) == -1) {
+ (void) fprintf(stderr, "open(%s) failed: %d\n", tfile, errno);
+ return (1);
+ }
+ (void) close(fd);
+
+ for (i = 0; i < NCOMMAND; i++) {
+ time_t t1, t2;
+
+ /*
+ * Get original time before operating.
+ */
+ ret = get_file_time(tfile, timetest_table[i].type, &t1);
+ if (ret != 0) {
+ (void) fprintf(stderr, "get_file_time(%s %d) = %d\n",
+ tfile, timetest_table[i].type, ret);
+ return (1);
+ }
+
+ /*
+ * Sleep 2 seconds, then invoke command on given file
+ */
+ (void) sleep(2);
+ timetest_table[i].func(tfile);
+
+ /*
+ * Get time after operating.
+ */
+ ret = get_file_time(tfile, timetest_table[i].type, &t2);
+ if (ret != 0) {
+ (void) fprintf(stderr, "get_file_time(%s %d) = %d\n",
+ tfile, timetest_table[i].type, ret);
+ return (1);
+ }
+
+ if (t1 == t2) {
+ (void) fprintf(stderr, "%s: t1(%ld) == t2(%ld)\n",
+ timetest_table[i].name, (long)t1, (long)t2);
+ return (1);
+ } else {
+ (void) fprintf(stderr, "%s: t1(%ld) != t2(%ld)\n",
+ timetest_table[i].name, (long)t1, (long)t2);
+ }
+ }
+
+ (void) fprintf(stdout, "PASS\n");
+ return (0);
+}