Whamcloud - gitweb
LU-13773 tests: subscript failure propagation
[fs/lustre-release.git] / lustre / tests / checkstat.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) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, Intel Corporation.
27  */
28 /*
29  * Test program to compare the attributes of a files to verify that it
30  * desired file attributes are present.  This file predates availability
31  * of the stat(3) utility and is deprecated.  Either test(3) ([ ]) or
32  * stat(3) should be used in all new tests.
33  *
34  * This file is part of Lustre, http://www.lustre.org/
35  * Lustre is a trademark of Sun Microsystems, Inc.
36  */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
43 #include <errno.h>
44 #include <string.h>
45 #include <pwd.h>
46 #include <grp.h>
47
48 void
49 usage(char *argv0, int help)
50 {
51         char *progname = strrchr(argv0, '/');
52
53         if (!progname)
54                 progname = argv0;
55
56         fprintf(help ? stdout : stderr,
57                 "Usage: %s [flags] file[s]\n",
58                 progname);
59
60         if (!help) {
61                 fprintf(stderr, "   or try '-h' for help\n");
62                 exit(1);
63         }
64
65         printf("Check given files have...\n");
66         printf(" -p    permission       file must have required permissions\n");
67         printf(" -t    dir|file|link    file must be of the specified type\n");
68         printf(" -l    link_name        file must be a link to the given name\n");
69         printf(" -s    size             file must have the given size\n");
70         printf(" -u    user             file must be owned by given user\n");
71         printf(" -g    group            file must be owned by given group\n");
72         printf(" -f                     follow symlinks\n");
73         printf(" -a                     file must be absent\n");
74         printf(" -v                     increase verbosity\n");
75         printf(" -h                     print help\n");
76         printf(" Exit status is 0 on success, 1 on failure\n");
77 }
78
79 int
80 main(int argc, char **argv)
81 {
82         int c;
83         struct stat64 buf;
84         int perms = -1;
85         uid_t uid = (uid_t)-1;
86         gid_t gid = (gid_t)-1;
87         char *type = NULL;
88         long absent = 0;
89         char *checklink = NULL;
90         int verbose = 0;
91         long long size = -1;
92         int follow = 0;
93         char *term;
94
95         while ((c = getopt(argc, argv, "p:t:l:s:u:g:avfh")) != -1)
96                 switch (c) {
97                 case 'p':
98                         perms = (int)strtol(optarg, &term, 0);
99                         if (term == optarg) {
100                                 fprintf(stderr, "Can't parse permission %s\n",
101                                         optarg);
102                                 return 1;
103                         }
104                         break;
105
106                 case 'l':
107                         checklink = optarg;
108                         break;
109
110                 case 's':
111                         size = strtoll(optarg, &term, 0);
112                         if (term == optarg) {
113                                 fprintf(stderr, "Can't parse size %s\n",
114                                         optarg);
115                                 return 1;
116                         }
117                         break;
118
119                 case 'u':
120                         if (*optarg == '#') {
121                                 uid = (uid_t)strtol(optarg + 1, &term, 0);
122
123                                 if (term == optarg + 1) {
124                                         fprintf(stderr,
125                                                 "Can't parse numeric uid %s\n",
126                                                 optarg);
127                                         return 1;
128                                 }
129                         } else {
130                                 struct passwd *pw = getpwnam(optarg);
131
132                                 if (!pw) {
133                                         fprintf(stderr, "Can't find user %s\n",
134                                                 optarg);
135                                         return 1;
136                                 }
137                                 uid = pw->pw_uid;
138                         }
139                         break;
140
141                 case 'g':
142                         if (*optarg == '#') {
143                                 gid = (gid_t)strtol(optarg + 1, &term, 0);
144
145                                 if (term == optarg + 1) {
146                                         fprintf(stderr,
147                                                 "Can't parse numeric gid %s\n",
148                                                 optarg);
149                                         return 1;
150                                 }
151                         } else {
152                                 struct group *gr = getgrnam(optarg);
153
154                                 if (!gr) {
155                                         fprintf(stderr,
156                                                 "Can't find group %s\n",
157                                                 optarg);
158                                         return 1;
159                                 }
160                                 uid = gr->gr_gid;
161                         }
162                         break;
163
164                 case 't':
165                         type = optarg;
166                         break;
167
168                 case 'a':
169                         absent = 1;
170                         break;
171
172                 case 'v':
173                         verbose++;
174                         break;
175
176                 case 'f':
177                         follow++;
178                         break;
179
180                 case 'h':
181                         usage(argv[0], 1);
182                         return 0;
183
184                 default:
185                         usage(argv[0], 0);
186                 }
187
188         if (optind == argc)
189                 usage(argv[0], 0);
190
191         do {
192                 char *fname = argv[optind];
193                 int rc = follow ? stat64(fname, &buf) : lstat64(fname, &buf);
194
195                 if (rc != 0) {
196                         if (!(absent && errno == ENOENT)) {
197                                 if (verbose)
198                                         printf("Can't %sstat %s: %s\n",
199                                                follow ? "" : "l",
200                                                fname, strerror(errno));
201                                 return 1;
202                         }
203
204                         if (verbose)
205                                 printf("%s: absent OK\n", fname);
206                         continue;
207                 }
208
209                 if (absent) {
210                         if (verbose)
211                                 printf("%s exists\n", fname);
212                         return 1;
213                 }
214
215                 if (type) {
216                         if (!strcmp(type, "d") ||
217                             !strcmp(type, "dir")) {
218                                 if (!S_ISDIR(buf.st_mode)) {
219                                         if (verbose)
220                                                 printf("%s is not a directory\n",
221                                                        fname);
222                                         return 1;
223                                 }
224                         } else if (!strcmp(type, "f") ||
225                                  !strcmp(type, "file")) {
226                                 if (!S_ISREG(buf.st_mode)) {
227                                         if (verbose)
228                                                 printf("%s is not a regular file\n",
229                                                        fname);
230                                         return 1;
231                                 }
232                         } else if (!strcmp(type, "l") ||
233                                  !strcmp(type, "link")) {
234                                 if (!S_ISLNK(buf.st_mode)) {
235                                         if (verbose)
236                                                 printf("%s is not a link\n",
237                                                        fname);
238                                         return 1;
239                                 }
240                         } else {
241                                 fprintf(stderr, "Can't parse file type %s\n",
242                                         type);
243                                 return 1;
244                         }
245
246                         if (verbose)
247                                 printf("%s has type %s OK\n", fname, type);
248                 }
249
250                 if (perms != -1) {
251                         if ((buf.st_mode & ~S_IFMT) != perms) {
252                                 if (verbose)
253                                         printf("%s has perms 0%o, not 0%o\n",
254                                                fname, (buf.st_mode & ~S_IFMT),
255                                                perms);
256                                 return 1;
257                         }
258
259                         if (verbose)
260                                 printf("%s has perms 0%o OK\n",
261                                        fname, perms);
262                 }
263
264                 if (size != -1) {
265                         if (buf.st_size != size) {
266                                 if (verbose)
267                                         printf("%s has size %lld, not %lld\n",
268                                                fname, (long long)buf.st_size,
269                                                size);
270                                 return 1;
271                         }
272
273                         if (verbose)
274                                 printf("%s has size %lld OK\n", fname, size);
275                 }
276
277                 if (checklink) {
278                         static char lname[4 << 10];
279
280                         rc = readlink(fname, lname, sizeof(lname) - 1);
281
282                         if (rc < 0) {
283                                 if (verbose)
284                                         printf("%s: can't read link: %s\n",
285                                                fname, strerror(errno));
286                                 return 1;
287                         }
288
289                         lname[rc] = 0;
290                         if (strcmp(checklink, lname)) {
291                                 if (verbose)
292                                         printf("%s is a link to %s and not %s\n",
293                                                fname, lname, checklink);
294                                 return 1;
295                         }
296
297                         if (verbose)
298                                 printf("%s links to %s OK\n", fname, checklink);
299                 }
300
301                 if (uid != (uid_t)-1) {
302                         if (buf.st_uid != uid) {
303                                 if (verbose)
304                                         printf("%s is owned by user #%ld and not #%ld\n",
305                                                fname, (long)buf.st_uid, (long)uid);
306                                 return 1;
307                         }
308
309                         if (verbose)
310                                 printf("%s is owned by user #%ld OK\n",
311                                        fname, (long)uid);
312                 }
313
314                 if (gid != (gid_t)-1) {
315                         if (buf.st_gid != gid) {
316                                 if (verbose)
317                                         printf("%s is owned by group #%ld and not #%ld\n",
318                                                fname, (long)buf.st_gid, (long)gid);
319                                 return 1;
320                         }
321
322                         if (verbose)
323                                 printf("%s is owned by group #%ld OK\n",
324                                        fname, (long)gid);
325                 }
326         } while (++optind < argc);
327
328         return 0;
329 }