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