]> git.ipfire.org Git - thirdparty/util-linux.git/blame - shlibs/mount/src/utils.c
libmount: add mnt_split_optstr()
[thirdparty/util-linux.git] / shlibs / mount / src / utils.c
CommitLineData
69b7e41e
KZ
1/*
2 * Copyright (C) 2008-2009 Karel Zak <kzak@redhat.com>
3 *
4 * This file may be redistributed under the terms of the
5 * GNU Lesser General Public License.
6 */
7
192c6aad
KZ
8/**
9 * SECTION: utils
10 * @title: Utils
11 * @short_description: misc utils.
12 */
69b7e41e
KZ
13#include <unistd.h>
14#include <errno.h>
15#include <stdlib.h>
16#include <string.h>
17#ifdef HAVE_SYS_PRCTL_H
18#include <sys/prctl.h>
19#else
20#define PR_GET_DUMPABLE 3
21#endif
22#if (!defined(HAVE_PRCTL) && defined(linux))
23#include <sys/syscall.h>
24#endif
25#include <sys/stat.h>
26#include <ctype.h>
27#include <sys/types.h>
28#include <fcntl.h>
29#include <pwd.h>
30
31#include "mountP.h"
32
33char *mnt_getenv_safe(const char *arg)
34{
35 if ((getuid() != geteuid()) || (getgid() != getegid()))
36 return NULL;
37#if HAVE_PRCTL
38 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
39 return NULL;
40#else
41#if (defined(linux) && defined(SYS_prctl))
42 if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
43 return NULL;
44#endif
45#endif
46
47#ifdef HAVE___SECURE_GETENV
48 return __secure_getenv(arg);
49#else
50 return getenv(arg);
51#endif
52}
53
69b7e41e
KZ
54/**
55 * mnt_fstype_is_pseudofs:
56 * @type: filesystem name
57 *
58 * Returns: 1 for filesystems like proc, sysfs, ... or 0.
59 */
60int mnt_fstype_is_pseudofs(const char *type)
61{
62 if (!type)
63 return 0;
64 if (strcmp(type, "none") == 0 ||
65 strcmp(type, "proc") == 0 ||
66 strcmp(type, "tmpfs") == 0 ||
67 strcmp(type, "sysfs") == 0 ||
68 strcmp(type, "devpts") == 0||
69 strcmp(type, "cgroups") == 0 ||
70 strcmp(type, "devfs") == 0 ||
71 strcmp(type, "dlmfs") == 0 ||
72 strcmp(type, "cpuset") == 0 ||
73 strcmp(type, "spufs") == 0)
74 return 1;
75 return 0;
76}
77
78/**
79 * mnt_fstype_is_netfs:
80 * @type: filesystem name
81 *
82 * Returns: 1 for filesystems like cifs, nfs, ... or 0.
83 */
84int mnt_fstype_is_netfs(const char *type)
85{
86 if (!type)
87 return 0;
88 if (strcmp(type, "cifs") == 0 ||
89 strcmp(type, "smbfs") == 0 ||
90 strncmp(type, "nfs", 3) == 0 ||
91 strcmp(type, "afs") == 0 ||
92 strcmp(type, "ncpfs") == 0)
93 return 1;
94 return 0;
95}
96
abc9c0f7
KZ
97/**
98 * mnt_match_fstype:
99 * @type: filesystem type
100 * @pattern: filesystem name or comma delimitted list of names
101 *
102 * The @pattern list of filesystem can be prefixed with a global
103 * "no" prefix to invert matching of the whole list. The "no" could
3d735589
KZ
104 * also used for individual items in the @pattern list. So,
105 * "nofoo,bar" has the same meaning as "nofoo,nobar".
abc9c0f7 106 *
3d735589
KZ
107 * "bar" : "nofoo,bar" -> False (global "no" prefix)
108 *
109 * "bar" : "foo,bar" -> True
abc9c0f7 110 *
abc9c0f7
KZ
111 * "bar" : "foo,nobar" -> False
112 *
113 * Returns: 1 if type is matching, else 0. This function also returns
114 * 0 if @pattern is NULL and @type is non-NULL.
115 */
116int mnt_match_fstype(const char *type, const char *pattern)
117{
118 int no = 0; /* negated types list */
119 int len;
120 const char *p;
121
122 if (!pattern && !type)
123 return 1;
124 if (!pattern)
125 return 0;
126
127 if (!strncmp(pattern, "no", 2)) {
128 no = 1;
129 pattern += 2;
130 }
131
132 /* Does type occur in types, separated by commas? */
133 len = strlen(type);
134 p = pattern;
135 while(1) {
136 if (!strncmp(p, "no", 2) && !strncmp(p+2, type, len) &&
137 (p[len+2] == 0 || p[len+2] == ','))
138 return 0;
139 if (strncmp(p, type, len) == 0 && (p[len] == 0 || p[len] == ','))
140 return !no;
141 p = strchr(p,',');
142 if (!p)
143 break;
144 p++;
145 }
146 return no;
147}
148
149
150/* Returns 1 if needle found or noneedle not found in haystack
151 * Otherwise returns 0
152 */
153static int check_option(const char *haystack, size_t len,
154 const char *needle, size_t needle_len)
155{
156 const char *p;
157 int no = 0;
158
159 if (needle_len >= 2 && !strncmp(needle, "no", 2)) {
160 no = 1;
161 needle += 2;
162 needle_len -= 2;
163 }
164
165 for (p = haystack; p && p < haystack + len; p++) {
166 char *sep = strchr(p, ',');
167 size_t plen = sep ? sep - p : len - (p - haystack);
168
169 if (plen == needle_len) {
170 if (!strncmp(p, needle, plen))
171 return !no; /* foo or nofoo was found */
172 }
173 p += plen;
174 }
175
176 return no; /* foo or nofoo was not found */
177}
178
179/**
180 * mnt_match_options:
181 * @optstr: options string
182 * @pattern: comma delimitted list of options
183 *
184 * The "no" could used for individual items in the @options list. The "no"
185 * prefix does not have a global meanning.
186 *
187 * Unlike fs type matching, nonetdev,user and nonetdev,nouser have
188 * DIFFERENT meanings; each option is matched explicitly as specified.
189 *
3d735589
KZ
190 * "xxx,yyy,zzz" : "nozzz" -> False
191 *
192 * "xxx,yyy,zzz" : "xxx,noeee" -> True
abc9c0f7
KZ
193 *
194 * Returns: 1 if pattern is matching, else 0. This function also returns 0
195 * if @pattern is NULL and @optstr is non-NULL.
196 */
197int mnt_match_options(const char *optstr, const char *pattern)
198{
199 const char *p;
200 size_t len, optstr_len = 0;
201
202 if (!pattern && !optstr)
203 return 1;
204 if (!pattern)
205 return 0;
206
207 len = strlen(pattern);
208 if (optstr)
209 optstr_len = strlen(optstr);
210
211 for (p = pattern; p < pattern + len; p++) {
212 char *sep = strchr(p, ',');
213 size_t plen = sep ? sep - p : len - (p - pattern);
214
215 if (!plen)
216 continue; /* if two ',' appear in a row */
217
218 if (!check_option(optstr, optstr_len, p, plen))
219 return 0; /* any match failure means failure */
220
221 p += plen;
222 }
223
224 /* no match failures in list means success */
225 return 1;
226}
227
69b7e41e
KZ
228/*
229 * Returns allocated string with username or NULL.
230 */
231char *mnt_get_username(const uid_t uid)
232{
233 struct passwd pwd;
234 struct passwd *res;
235 size_t sz = sysconf(_SC_GETPW_R_SIZE_MAX);
236 char *buf, *username = NULL;
237
238 if (sz <= 0)
239 sz = 16384; /* Should be more than enough */
240
241 buf = malloc(sz);
242 if (!buf)
243 return NULL;
244
245 if (!getpwuid_r(uid, &pwd, buf, sz, &res) && res)
246 username = strdup(pwd.pw_name);
247
248 free(buf);
249 return username;
250}
abc9c0f7
KZ
251
252#ifdef TEST_PROGRAM
253int test_match_fstype(struct mtest *ts, int argc, char *argv[])
254{
255 char *type = argv[1];
256 char *pattern = argv[2];
257
258 printf("%s\n", mnt_match_fstype(type, pattern) ? "MATCH" : "NOT-MATCH");
259 return 0;
260}
261
262int test_match_options(struct mtest *ts, int argc, char *argv[])
263{
264 char *optstr = argv[1];
265 char *pattern = argv[2];
266
267 printf("%s\n", mnt_match_options(optstr, pattern) ? "MATCH" : "NOT-MATCH");
268 return 0;
269}
270
271
272int main(int argc, char *argv[])
273{
274 struct mtest tss[] = {
275 { "--match-fstype", test_match_fstype, "<type> <pattern> FS types matching" },
276 { "--match-options", test_match_options, "<options> <pattern> options matching" },
277 { NULL }
278 };
279
280 return mnt_run_test(tss, argc, argv);
281}
282
283#endif /* TEST_PROGRAM */