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