Whamcloud - gitweb
LU-10657 utils: fd leak in mirror_split()
[fs/lustre-release.git] / lustre / tests / utime.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * This file is part of Lustre, http://www.lustre.org/
28  * Lustre is a trademark of Sun Microsystems, Inc.
29  *
30  * lustre/tests/utime.c
31  *
32  * Simple test for validating mtime on a file create and set via utime.
33  */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 #include <time.h>
42 #include <string.h>
43 #include <utime.h>
44 #include <errno.h>
45
46 void usage(char *prog)
47 {
48         fprintf(stderr, "usage: %s <filename> [-s <filename>]\n", prog);
49         exit(1);
50 }
51
52 int main(int argc, char *argv[])
53 {
54         long before_mknod, after_mknod;
55         const char *prog = argv[0];
56         const char *filename = argv[1];
57         char *secname = NULL;
58         struct utimbuf utb;
59         struct stat st, st2;
60         int rc;
61         int c;
62
63         while ((c = getopt(argc, argv, "s:")) != -1) {
64                 switch(c) {
65                 case 's':
66                         secname = optarg;
67                         break;
68                 default:
69                         usage(argv[0]);
70                 }
71         }
72         if (optind + 1 > argc)
73                 usage(argv[0]);
74
75         /* Adjust the before time back one second, because the kernel's
76          * CURRENT_TIME (lockless clock reading, used to set inode times)
77          * may drift against the do_gettimeofday() time (TSC-corrected and
78          * locked clock reading, used to return timestamps to user space).
79          * This means that the mknod time could be a second older than the
80          * before time, even for a local filesystem such as ext3.
81          */
82         before_mknod = time(0) - 1;
83         rc = mknod(filename, 0700, S_IFREG);
84         after_mknod = time(0);
85         if (rc && errno != EEXIST) {
86                 fprintf(stderr, "%s: mknod(%s) failed: rc %d: %s\n",
87                         prog, filename, errno, strerror(errno));
88                 return 2;
89         } else if (!rc) {
90                 rc = stat(filename, &st);
91                 if (rc) {
92                         fprintf(stderr, "%s: stat(%s) failed: rc %d: %s\n",
93                                 prog, filename, errno, strerror(errno));
94                         return 3;
95                 }
96
97                 if (st.st_mtime < before_mknod || st.st_mtime > after_mknod) {
98                         fprintf(stderr, "%s: bad mknod(%s) times %lu <= %lu <= "
99                                 "%lu false\n", prog, filename, before_mknod,
100                                 st.st_mtime, after_mknod);
101                         return 4;
102                 }
103
104                 printf("%s: good mknod times %lu%s <= %lu <= %lu for %s\n",
105                        prog, before_mknod, before_mknod == st.st_mtime ? "*":"",
106                        st.st_mtime, after_mknod, filename);
107
108                 if (secname) {
109                         sleep(1);
110                         rc = stat(secname, &st2);
111                         if (rc) {
112                                 fprintf(stderr, "%s: stat(%s) failed: rc %d: "
113                                         "%s\n", prog, secname, errno,
114                                         strerror(errno));
115                                 return 5;
116                         }
117
118                         if (st2.st_mtime < before_mknod || 
119                             st2.st_mtime > after_mknod) {
120                                 fprintf(stderr, "%s: bad mknod(%s) times %lu "
121                                         " <= %lu <= %lu false\n", prog,
122                                         filename, before_mknod, st2.st_mtime,
123                                         after_mknod);
124                                 return 6;
125                         }
126
127                         printf("%s: good mknod times %lu%s <= %lu <= %lu "
128                                "for %s\n", prog, before_mknod, 
129                                before_mknod == st.st_mtime ? "*":"", 
130                                st2.st_mtime, after_mknod, secname);
131                 }
132         }
133
134         utb.actime = 200000;
135         utb.modtime = 100000;
136         rc = utime(filename, &utb);
137         if (rc) {
138                 fprintf(stderr, "%s: utime(%s) failed: rc %d: %s\n",
139                         prog, filename, errno, strerror(errno));
140                 return 7;
141         }
142         
143         rc = stat(filename, &st);
144         if (rc) {
145                 fprintf(stderr, "%s: second stat(%s) failed: rc %d: %s\n",
146                         prog, filename, errno, strerror(errno));
147                 return 8;
148         }
149
150         if (st.st_mtime != utb.modtime ) {
151                 fprintf(stderr, "%s: bad utime mtime(%s) %lu should be %lu\n",
152                         prog, filename, st.st_mtime, utb.modtime);
153                 return 9;
154         }
155
156         if (st.st_atime != utb.actime ) {
157                 fprintf(stderr, "%s: bad utime atime(%s) %lu should be %lu\n",
158                         prog, filename, st.st_atime, utb.actime);
159                 return 10;
160         }
161
162         printf("%s: good utime mtimes %lu, atime %lu\n",
163                prog, utb.modtime, utb.actime);
164
165         if (secname == NULL)
166                 return 0;
167         
168         /* Checking that times in past get updated on another client. */
169         rc = stat(secname, &st2);
170         if (rc) {
171                 fprintf(stderr, "%s: second stat(%s) failed: rc %d: %s\n",
172                         prog, secname, errno, strerror(errno));
173                 return 12;
174         }
175
176         if (st2.st_mtime != st.st_mtime) {
177                 fprintf(stderr, "%s: not synced mtime(%s) between clients: "
178                         "%lu should be %lu\n", prog, secname,
179                         st2.st_mtime, st.st_mtime);
180                 return 13;
181         }
182
183         if (st2.st_ctime != st.st_ctime) {
184                 fprintf(stderr, "%s: not synced ctime(%s) between clients: "
185                         "%lu should be %lu\n", prog, secname,
186                         st2.st_ctime, st.st_ctime);
187                 return 14;
188         }
189         
190         printf("%s: updated times for %s\n", prog, secname);
191         
192         return 0;
193 }