pathchk.c - sbase - suckless unix tools | |
git clone git://git.suckless.org/sbase | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
pathchk.c (2341B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include <sys/stat.h> | |
3 | |
4 #include <errno.h> | |
5 #include <limits.h> | |
6 #include <stdint.h> | |
7 #include <stdio.h> | |
8 #include <stdlib.h> | |
9 #include <string.h> | |
10 | |
11 #include "util.h" | |
12 | |
13 #define PORTABLE_CHARACTER_SET "0123456789._-qwertyuiopasdfghjklzxcvbnmQ… | |
14 /* If your system supports more other characters, but not all non-NUL ch… | |
15 | |
16 static int most = 0; | |
17 static int extra = 0; | |
18 | |
19 static int | |
20 pathchk(char *filename) | |
21 { | |
22 char *invalid, *invalid_end, *p, *q; | |
23 const char *character_set; | |
24 size_t len, maxlen; | |
25 struct stat st; | |
26 | |
27 /* Empty? */ | |
28 if (extra && !*filename) | |
29 eprintf("empty filename\n"); | |
30 | |
31 /* Leading hyphen? */ | |
32 if (extra && ((*filename == '-') || strstr(filename, "/-"))) | |
33 eprintf("%s: leading '-' in component of filename\n", fi… | |
34 | |
35 /* Nonportable character? */ | |
36 #ifdef SYSTEM_CHARACTER_SET | |
37 character_set = "/"SYSTEM_CHARACTER_SET; | |
38 #else | |
39 character_set = 0; | |
40 #endif | |
41 if (most) | |
42 character_set = "/"PORTABLE_CHARACTER_SET; | |
43 if (character_set && *(invalid = filename + strspn(filename, cha… | |
44 for (invalid_end = invalid + 1; *invalid_end & 0x80; inv… | |
45 p = estrdup(filename); | |
46 *invalid_end = 0; | |
47 eprintf("%s: nonportable character '%s'\n", p, invalid); | |
48 } | |
49 | |
50 /* Symlink error? Non-searchable directory? */ | |
51 if (lstat(filename, &st) && errno != ENOENT) { | |
52 /* lstat rather than stat, so that if filename is a bad … | |
53 * all parents are OK, no error will be detected. */ | |
54 eprintf("%s:", filename); | |
55 } | |
56 | |
57 /* Too long pathname? */ | |
58 maxlen = most ? _POSIX_PATH_MAX : PATH_MAX; | |
59 if (strlen(filename) >= maxlen) | |
60 eprintf("%s: is longer than %zu bytes\n", filename, maxl… | |
61 | |
62 /* Too long component? */ | |
63 maxlen = most ? _POSIX_NAME_MAX : NAME_MAX; | |
64 for (p = filename; p; p = q) { | |
65 q = strchr(p, '/'); | |
66 len = q ? (size_t)(q++ - p) : strlen(p); | |
67 if (len > maxlen) | |
68 eprintf("%s: includes component longer than %zu … | |
69 filename, maxlen); | |
70 } | |
71 | |
72 return 0; | |
73 } | |
74 | |
75 static void | |
76 usage(void) | |
77 { | |
78 eprintf("usage: %s [-pP] filename...\n", argv0); | |
79 } | |
80 | |
81 int | |
82 main(int argc, char *argv[]) | |
83 { | |
84 int ret = 0; | |
85 | |
86 ARGBEGIN { | |
87 case 'p': | |
88 most = 1; | |
89 break; | |
90 case 'P': | |
91 extra = 1; | |
92 break; | |
93 default: | |
94 usage(); | |
95 } ARGEND | |
96 | |
97 if (!argc) | |
98 usage(); | |
99 | |
100 for (; argc--; argv++) | |
101 ret |= pathchk(*argv); | |
102 | |
103 return ret; | |
104 } |