Whamcloud - gitweb
LU-15210 tests: fix sanity-lnet to handle duplicate IP
[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  */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <unistd.h>
42 #include <errno.h>
43 #include <string.h>
44 #include <pwd.h>
45 #include <grp.h>
46
47 void
48 usage(char *argv0, int help)
49 {
50         char *progname = strrchr(argv0, '/');
51
52         if (!progname)
53                 progname = argv0;
54
55         fprintf(help ? stdout : stderr,
56                 "Usage: %s [flags] file[s]\n",
57                 progname);
58
59         if (!help) {
60                 fprintf(stderr, "   or try '-h' for help\n");
61                 exit(1);
62         }
63
64         printf("Check given files have...\n");
65         printf(" -p    permission       file must have required permissions\n");
66         printf(" -t    dir|file|link    file must be of the specified type\n");
67         printf(" -l    link_name        file must be a link to the given name\n");
68         printf(" -s    size             file must have the given size\n");
69         printf(" -u    user             file must be owned by given user\n");
70         printf(" -g    group            file must be owned by given group\n");
71         printf(" -f                     follow symlinks\n");
72         printf(" -a                     file must be absent\n");
73         printf(" -v                     increase verbosity\n");
74         printf(" -h                     print help\n");
75         printf(" Exit status is 0 on success, 1 on failure\n");
76 }
77
78 /* using realpath() implies the paths must be resolved/exist
79  * so this will fail for dangling links
80  */
81 int check_canonical(char *lname, char *checklink, int verbose)
82 {
83         char *lname_canon;
84         char *checklink_canon;
85
86         lname_canon = realpath(lname, NULL);
87         if (lname_canon == NULL) {
88                 if (verbose)
89                         printf("%s: can't canonicalize: %s\n",
90                                lname, strerror(errno));
91                 return 1;
92         }
93
94         checklink_canon = realpath(checklink, NULL);
95         if (checklink_canon == NULL) {
96                 if (verbose)
97                         printf("%s: can't canonicalize: %s\n",
98                                checklink, strerror(errno));
99                 return 1;
100         }
101
102         if (strcmp(checklink_canon, lname_canon)) {
103                 free(lname_canon);
104                 free(checklink_canon);
105                 return 1;
106         }
107         free(lname_canon);
108         free(checklink_canon);
109         return 0;
110 }
111
112 int
113 main(int argc, char **argv)
114 {
115         int c;
116         struct stat64 buf;
117         int perms = -1;
118         uid_t uid = (uid_t)-1;
119         gid_t gid = (gid_t)-1;
120         char *type = NULL;
121         long absent = 0;
122         char *checklink = NULL;
123         int verbose = 0;
124         long long size = -1;
125         int follow = 0;
126         char *term;
127
128         while ((c = getopt(argc, argv, "p:t:l:s:u:g:avfh")) != -1)
129                 switch (c) {
130                 case 'p':
131                         perms = (int)strtol(optarg, &term, 0);
132                         if (term == optarg) {
133                                 fprintf(stderr, "Can't parse permission %s\n",
134                                         optarg);
135                                 return 1;
136                         }
137                         break;
138
139                 case 'l':
140                         checklink = optarg;
141                         break;
142
143                 case 's':
144                         size = strtoll(optarg, &term, 0);
145                         if (term == optarg) {
146                                 fprintf(stderr, "Can't parse size %s\n",
147                                         optarg);
148                                 return 1;
149                         }
150                         break;
151
152                 case 'u':
153                         if (*optarg == '#') {
154                                 uid = (uid_t)strtol(optarg + 1, &term, 0);
155
156                                 if (term == optarg + 1) {
157                                         fprintf(stderr,
158                                                 "Can't parse numeric uid %s\n",
159                                                 optarg);
160                                         return 1;
161                                 }
162                         } else {
163                                 struct passwd *pw = getpwnam(optarg);
164
165                                 if (!pw) {
166                                         fprintf(stderr, "Can't find user %s\n",
167                                                 optarg);
168                                         return 1;
169                                 }
170                                 uid = pw->pw_uid;
171                         }
172                         break;
173
174                 case 'g':
175                         if (*optarg == '#') {
176                                 gid = (gid_t)strtol(optarg + 1, &term, 0);
177
178                                 if (term == optarg + 1) {
179                                         fprintf(stderr,
180                                                 "Can't parse numeric gid %s\n",
181                                                 optarg);
182                                         return 1;
183                                 }
184                         } else {
185                                 struct group *gr = getgrnam(optarg);
186
187                                 if (!gr) {
188                                         fprintf(stderr,
189                                                 "Can't find group %s\n",
190                                                 optarg);
191                                         return 1;
192                                 }
193                                 uid = gr->gr_gid;
194                         }
195                         break;
196
197                 case 't':
198                         type = optarg;
199                         break;
200
201                 case 'a':
202                         absent = 1;
203                         break;
204
205                 case 'v':
206                         verbose++;
207                         break;
208
209                 case 'f':
210                         follow++;
211                         break;
212
213                 case 'h':
214                         usage(argv[0], 1);
215                         return 0;
216
217                 default:
218                         usage(argv[0], 0);
219                 }
220
221         if (optind == argc)
222                 usage(argv[0], 0);
223
224         do {
225                 char *fname = argv[optind];
226                 int rc = follow ? stat64(fname, &buf) : lstat64(fname, &buf);
227
228                 if (rc != 0) {
229                         if (!(absent && errno == ENOENT)) {
230                                 if (verbose)
231                                         printf("Can't %sstat %s: %s\n",
232                                                follow ? "" : "l",
233                                                fname, strerror(errno));
234                                 return 1;
235                         }
236
237                         if (verbose)
238                                 printf("%s: absent OK\n", fname);
239                         continue;
240                 }
241
242                 if (absent) {
243                         if (verbose)
244                                 printf("%s exists\n", fname);
245                         return 1;
246                 }
247
248                 if (type) {
249                         if (!strcmp(type, "d") ||
250                             !strcmp(type, "dir")) {
251                                 if (!S_ISDIR(buf.st_mode)) {
252                                         if (verbose)
253                                                 printf("%s is not a directory\n",
254                                                        fname);
255                                         return 1;
256                                 }
257                         } else if (!strcmp(type, "f") ||
258                                  !strcmp(type, "file")) {
259                                 if (!S_ISREG(buf.st_mode)) {
260                                         if (verbose)
261                                                 printf("%s is not a regular file\n",
262                                                        fname);
263                                         return 1;
264                                 }
265                         } else if (!strcmp(type, "l") ||
266                                  !strcmp(type, "link")) {
267                                 if (!S_ISLNK(buf.st_mode)) {
268                                         if (verbose)
269                                                 printf("%s is not a link\n",
270                                                        fname);
271                                         return 1;
272                                 }
273                         } else {
274                                 fprintf(stderr, "Can't parse file type %s\n",
275                                         type);
276                                 return 1;
277                         }
278
279                         if (verbose)
280                                 printf("%s has type %s OK\n", fname, type);
281                 }
282
283                 if (perms != -1) {
284                         if ((buf.st_mode & ~S_IFMT) != perms) {
285                                 if (verbose)
286                                         printf("%s has perms 0%o, not 0%o\n",
287                                                fname, (buf.st_mode & ~S_IFMT),
288                                                perms);
289                                 return 1;
290                         }
291
292                         if (verbose)
293                                 printf("%s has perms 0%o OK\n",
294                                        fname, perms);
295                 }
296
297                 if (size != -1) {
298                         if (buf.st_size != size) {
299                                 if (verbose)
300                                         printf("%s has size %lld, not %lld\n",
301                                                fname, (long long)buf.st_size,
302                                                size);
303                                 return 1;
304                         }
305
306                         if (verbose)
307                                 printf("%s has size %lld OK\n", fname, size);
308                 }
309
310                 if (checklink) {
311                         static char lname[4 << 10];
312
313                         rc = readlink(fname, lname, sizeof(lname) - 1);
314
315                         if (rc < 0) {
316                                 if (verbose)
317                                         printf("%s: can't read link: %s\n",
318                                                fname, strerror(errno));
319                                 return 1;
320                         }
321
322                         lname[rc] = 0;
323
324                         /* just in case, try to also match the canonicalized
325                          * paths
326                          */
327                         if (strcmp(checklink, lname) &&
328                             check_canonical(lname, checklink, verbose)) {
329                                 if (verbose)
330                                         printf("%s is a link to %s and not %s\n",
331                                                fname, lname, checklink);
332                                 return 1;
333                         }
334
335                         if (verbose)
336                                 printf("%s links to %s OK\n", fname, checklink);
337                 }
338
339                 if (uid != (uid_t)-1) {
340                         if (buf.st_uid != uid) {
341                                 if (verbose)
342                                         printf("%s is owned by user #%ld and not #%ld\n",
343                                                fname, (long)buf.st_uid, (long)uid);
344                                 return 1;
345                         }
346
347                         if (verbose)
348                                 printf("%s is owned by user #%ld OK\n",
349                                        fname, (long)uid);
350                 }
351
352                 if (gid != (gid_t)-1) {
353                         if (buf.st_gid != gid) {
354                                 if (verbose)
355                                         printf("%s is owned by group #%ld and not #%ld\n",
356                                                fname, (long)buf.st_gid, (long)gid);
357                                 return 1;
358                         }
359
360                         if (verbose)
361                                 printf("%s is owned by group #%ld OK\n",
362                                        fname, (long)gid);
363                 }
364         } while (++optind < argc);
365
366         return 0;
367 }