xref: /freebsd/contrib/libarchive/cpio/test/test_option_a.c (revision bd66c1b43e33540205dbc1187c2f2a15c58b57ba)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2003-2008 Tim Kientzle
5  * All rights reserved.
6  */
7 #include "test.h"
8 #if defined(HAVE_UTIME_H)
9 #include <utime.h>
10 #elif defined(HAVE_SYS_UTIME_H)
11 #include <sys/utime.h>
12 #endif
13 
14 static struct {
15 	const char *name;
16 	time_t atime_sec;
17 } files[] = {
18 	{ "f0", 0 },
19 	{ "f1", 0 },
20 	{ "f2", 0 },
21 	{ "f3", 0 },
22 	{ "f4", 0 },
23 	{ "f5", 0 }
24 };
25 
26 /*
27  * Create a bunch of test files and record their atimes.
28  * For the atime preserve/change tests, the files must have
29  * atimes in the past.  We can accomplish this by explicitly invoking
30  * utime() on platforms that support it or by simply sleeping
31  * for a second after creating the files.  (Creating all of the files
32  * at once means we only need to sleep once.)
33  */
34 static void
test_create(void)35 test_create(void)
36 {
37 	struct stat st;
38 	struct utimbuf times;
39 	static const int numfiles = sizeof(files) / sizeof(files[0]);
40 	int i;
41 
42 	for (i = 0; i < numfiles; ++i) {
43 		/*
44 		 * Note: Have to write at least one byte to the file.
45 		 * cpio doesn't bother reading the file if it's zero length,
46 		 * so the atime never gets changed in that case, which
47 		 * makes the tests below rather pointless.
48 		 */
49 		assertMakeFile(files[i].name, 0644, "a");
50 
51 		/* If utime() isn't supported on your platform, just
52 		 * #ifdef this section out.  Most of the test below is
53 		 * still valid. */
54 		memset(&times, 0, sizeof(times));
55 #if defined(_WIN32) && !defined(CYGWIN)
56 		times.actime = 86400;
57 		times.modtime = 86400;
58 #else
59 		times.actime = 1;
60 		times.modtime = 3;
61 #endif
62 		assertEqualInt(0, utime(files[i].name, &times));
63 
64 		/* Record whatever atime the file ended up with. */
65 		/* If utime() is available, this should be 1, but there's
66 		 * no harm in being careful. */
67 		assertEqualInt(0, stat(files[i].name, &st));
68 		files[i].atime_sec = st.st_atime;
69 	}
70 
71 	/* Wait until the atime on the last file is actually in the past. */
72 	sleepUntilAfter(files[numfiles - 1].atime_sec);
73 }
74 
DEFINE_TEST(test_option_a)75 DEFINE_TEST(test_option_a)
76 {
77 	struct stat st;
78 	int r;
79 	char *p;
80 
81 	/* Create all of the test files. */
82 	test_create();
83 
84 	/* Sanity check; verify that atimes really do get modified. */
85 	p = slurpfile(NULL, "f0");
86 	assert(p != NULL);
87 	free(p);
88 	assertEqualInt(0, stat("f0", &st));
89 	if (st.st_atime == files[0].atime_sec) {
90 		skipping("Cannot verify -a option\n"
91 		    "      Your system appears to not support atime.");
92 	}
93 	else
94 	{
95 		/*
96 		 * If this disk is mounted noatime, then we can't
97 		 * verify correct operation without -a.
98 		 */
99 
100 		/* Copy the file without -a; should change the atime. */
101 		r = systemf("echo %s | %s -pd copy-no-a > copy-no-a.out 2>copy-no-a.err", files[1].name, testprog);
102 		assertEqualInt(r, 0);
103 		assertTextFileContents("1 block\n", "copy-no-a.err");
104 		assertEmptyFile("copy-no-a.out");
105 		assertEqualInt(0, stat(files[1].name, &st));
106 		failure("Copying file without -a should have changed atime.");
107 		assert(st.st_atime != files[1].atime_sec);
108 
109 		/* Archive the file without -a; should change the atime. */
110 		r = systemf("echo %s | %s -o > archive-no-a.out 2>archive-no-a.err", files[2].name, testprog);
111 		assertEqualInt(r, 0);
112 		assertTextFileContents("1 block\n", "copy-no-a.err");
113 		assertEqualInt(0, stat(files[2].name, &st));
114 		failure("Archiving file without -a should have changed atime.");
115 		assert(st.st_atime != files[2].atime_sec);
116 	}
117 
118 	/*
119 	 * We can, of course, still verify that the atime is unchanged
120 	 * when using the -a option.
121 	 */
122 
123 	/* Copy the file with -a; should not change the atime. */
124 	r = systemf("echo %s | %s -pad copy-a > copy-a.out 2>copy-a.err",
125 	    files[3].name, testprog);
126 	assertEqualInt(r, 0);
127 	assertTextFileContents("1 block\n", "copy-a.err");
128 	assertEmptyFile("copy-a.out");
129 	assertEqualInt(0, stat(files[3].name, &st));
130 	failure("Copying file with -a should not have changed atime.");
131 	assertEqualInt(st.st_atime, files[3].atime_sec);
132 
133 	/* Archive the file with -a; should not change the atime. */
134 	r = systemf("echo %s | %s -oa > archive-a.out 2>archive-a.err",
135 	    files[4].name, testprog);
136 	assertEqualInt(r, 0);
137 	assertTextFileContents("1 block\n", "copy-a.err");
138 	assertEqualInt(0, stat(files[4].name, &st));
139 	failure("Archiving file with -a should not have changed atime.");
140 	assertEqualInt(st.st_atime, files[4].atime_sec);
141 }
142