2 * Support functions. Exported functions are prototyped in sundries.h.
4 * added fcntl locking by Kjetil T. (kjetilho@math.uio.no) - aeb, 950927
6 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
7 * - added Native Language Support
13 #include <mntent.h> /* for MNTTYPE_SWAP */
15 #include "canonicalize.h"
27 xstrndup (const char *s, int n) {
31 die (EX_SOFTWARE, _("bug in xstrndup call"));
40 /* reallocates its first arg - typical use: s = xstrconcat3(s,t,u); */
42 xstrconcat3 (char *s, const char *t, const char *u) {
45 len = (s ? strlen(s) : 0) + (t ? strlen(t) : 0) + (u ? strlen(u) : 0);
54 s = xrealloc(s, len + 1);
62 /* frees its first arg - typical use: s = xstrconcat4(s,t,u,v); */
64 xstrconcat4 (char *s, const char *t, const char *u, const char *v) {
67 len = (s ? strlen(s) : 0) + (t ? strlen(t) : 0) +
68 (u ? strlen(u) : 0) + (v ? strlen(v) : 0);
77 s = xrealloc(s, len + 1);
89 /* Call this with SIG_BLOCK to block and SIG_UNBLOCK to unblock. */
91 block_signals (int how) {
95 sigdelset(&sigs, SIGTRAP);
96 sigdelset(&sigs, SIGSEGV);
97 sigprocmask (how, &sigs, (sigset_t *) 0);
101 /* Non-fatal error. Print message and return. */
102 /* (print the message in a single printf, in an attempt
103 to avoid mixing output of several threads) */
105 error (const char *fmt, ...) {
110 va_start (args, fmt);
111 vfprintf (stderr, fmt, args);
116 /* Fatal error. Print message and exit. */
117 void __attribute__ ((noreturn)) die(int err, const char *fmt, ...)
122 vfprintf(stderr, fmt, args);
123 fprintf(stderr, "\n");
129 /* True if fstypes match. Null *TYPES means match anything,
130 except that swap types always return false. */
131 /* Accept nonfs,proc,devpts and nonfs,noproc,nodevpts
132 with the same meaning. */
134 matching_type (const char *type, const char *types) {
135 int no; /* negated types list */
139 if (streq (type, MNTTYPE_SWAP))
145 if (!strncmp(types, "no", 2)) {
150 /* Does type occur in types, separated by commas? */
154 if (!strncmp(p, "no", 2) && !strncmp(p+2, type, len) &&
155 (p[len+2] == 0 || p[len+2] == ','))
157 if (strncmp(p, type, len) == 0 &&
158 (p[len] == 0 || p[len] == ','))
168 /* Returns 1 if needle found or noneedle not found in haystack
169 * Otherwise returns 0
172 check_option(const char *haystack, const char *needle) {
174 int len, needle_len, this_len;
178 if (!strncmp(needle, "no", 2)) {
182 needle_len = strlen(needle);
183 len = strlen(haystack);
185 for (p = haystack; p < haystack+len; p++) {
190 this_len = strlen(p);
192 if (this_len != needle_len) {
196 if (strncmp(p, needle, this_len) == 0)
197 return !no; /* foo or nofoo was found */
201 return no; /* foo or nofoo was not found */
205 /* Returns 1 if each of the test_opts options agrees with the entire
207 * Returns 0 if any noopt is found in test_opts and opt is found in options.
208 * Returns 0 if any opt is found in test_opts but is not found in options.
209 * Unlike fs type matching, nonetdev,user and nonetdev,nouser have
210 * DIFFERENT meanings; each option is matched explicitly as specified.
213 matching_opts (const char *options, const char *test_opts) {
218 if (test_opts == NULL)
223 len = strlen(test_opts);
226 die (EX_SYSERR, _("not enough memory"));
228 for (p = test_opts; p < test_opts+len; p++) {
233 this_len = strlen(p);
235 if (!this_len) continue; /* if two ',' appear in a row */
236 strncpy(q, p, this_len);
238 if (!check_option(options, q))
239 return 0; /* any match failure means failure */
243 /* no match failures in list means success */
248 is_pseudo_fs(const char *type)
250 if (type == NULL || *type == '/')
252 if (streq(type, "none") ||
253 streq(type, "proc") ||
254 streq(type, "tmpfs") ||
255 streq(type, "sysfs") ||
256 streq(type, "usbfs") ||
257 streq(type, "cgroup") ||
258 streq(type, "cpuset") ||
259 streq(type, "rpc_pipefs") ||
260 streq(type, "devpts") ||
261 streq(type, "securityfs") ||
262 streq(type, "debugfs"))
267 /* Make a canonical pathname from PATH. Returns a freshly malloced string.
268 It is up the *caller* to ensure that the PATH is sensible. i.e.
269 canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
270 is not a legal pathname for ``/dev/fd0''. Anything we cannot parse
271 we return unmodified. */
273 canonicalize_spec (const char *path)
279 if (nocanonicalize || is_pseudo_fs(path))
280 return xstrdup(path);
282 res = canonicalize_path(path);
284 die(EX_SYSERR, _("not enough memory"));
288 char *canonicalize (const char *path)
294 else if (nocanonicalize)
295 return xstrdup(path);
297 res = canonicalize_path(path);
299 die(EX_SYSERR, _("not enough memory"));