]> git.ipfire.org Git - thirdparty/glibc.git/blame - misc/mntent_r.c
aarch64: add STO_AARCH64_VARIANT_PCS and DT_AARCH64_VARIANT_PCS
[thirdparty/glibc.git] / misc / mntent_r.c
CommitLineData
845dcb57 1/* Utilities for reading/writing fstab, mtab, etc.
688903eb 2 Copyright (C) 1995-2018 Free Software Foundation, Inc.
df4ef2ab 3 This file is part of the GNU C Library.
845dcb57 4
df4ef2ab 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
845dcb57 9
df4ef2ab
UD
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
845dcb57 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
845dcb57 18
53308042 19#include <alloca.h>
845dcb57
UD
20#include <mntent.h>
21#include <stdio.h>
2706ee38 22#include <stdio_ext.h>
845dcb57
UD
23#include <string.h>
24#include <sys/types.h>
25
3ce1f295
UD
26#define flockfile(s) _IO_flockfile (s)
27#define funlockfile(s) _IO_funlockfile (s)
50304ef0 28
6b87a564
UD
29#undef __setmntent
30#undef __endmntent
31#undef __getmntent_r
32
845dcb57
UD
33/* Prepare to begin reading and/or writing mount table entries from the
34 beginning of FILE. MODE is as for `fopen'. */
35FILE *
36__setmntent (const char *file, const char *mode)
37{
ee8449f7 38 /* Extend the mode parameter with "c" to disable cancellation in the
312be3f9 39 I/O functions and "e" to set FD_CLOEXEC. */
ee8449f7 40 size_t modelen = strlen (mode);
312be3f9
UD
41 char newmode[modelen + 3];
42 memcpy (mempcpy (newmode, mode, modelen), "ce", 3);
ee8449f7 43 FILE *result = fopen (file, newmode);
2706ee38
UD
44
45 if (result != NULL)
46 /* We do the locking ourselves. */
b4c4f776 47 __fsetlocking (result, FSETLOCKING_BYCALLER);
2706ee38
UD
48
49 return result;
845dcb57 50}
30917259 51libc_hidden_def (__setmntent)
845dcb57
UD
52weak_alias (__setmntent, setmntent)
53
54
55/* Close a stream opened with `setmntent'. */
56int
57__endmntent (FILE *stream)
58{
59 if (stream) /* SunOS 4.x allows for NULL stream */
60 fclose (stream);
61 return 1; /* SunOS 4.x says to always return 1 */
62}
30917259 63libc_hidden_def (__endmntent)
845dcb57
UD
64weak_alias (__endmntent, endmntent)
65
66
b0b422e8
UD
67/* Since the values in a line are separated by spaces, a name cannot
68 contain a space. Therefore some programs encode spaces in names
69 by the strings "\040". We undo the encoding when reading an entry.
70 The decoding happens in place. */
71static char *
72decode_name (char *buf)
73{
74 char *rp = buf;
75 char *wp = buf;
76
77 do
78 if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '4' && rp[3] == '0')
79 {
80 /* \040 is a SPACE. */
81 *wp++ = ' ';
82 rp += 3;
83 }
37369d1c 84 else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '1')
b0b422e8 85 {
e796f92f 86 /* \011 is a TAB. */
b0b422e8
UD
87 *wp++ = '\t';
88 rp += 3;
89 }
37369d1c
UD
90 else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '2')
91 {
92 /* \012 is a NEWLINE. */
93 *wp++ = '\n';
94 rp += 3;
95 }
b0b422e8
UD
96 else if (rp[0] == '\\' && rp[1] == '\\')
97 {
98 /* We have to escape \\ to be able to represent all characters. */
99 *wp++ = '\\';
100 rp += 1;
101 }
21800751
UD
102 else if (rp[0] == '\\' && rp[1] == '1' && rp[2] == '3' && rp[3] == '4')
103 {
104 /* \134 is also \\. */
105 *wp++ = '\\';
106 rp += 3;
107 }
b0b422e8
UD
108 else
109 *wp++ = *rp;
110 while (*rp++ != '\0');
111
112 return buf;
113}
114
115
845dcb57
UD
116/* Read one mount table entry from STREAM. Returns a pointer to storage
117 reused on the next call, or null for EOF or error (use feof/ferror to
118 check). */
119struct mntent *
120__getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
121{
b0b422e8 122 char *cp;
845dcb57
UD
123 char *head;
124
71412a8c 125 flockfile (stream);
845dcb57
UD
126 do
127 {
128 char *end_ptr;
129
84e5e756 130 if (__fgets_unlocked (buffer, bufsiz, stream) == NULL)
4bae5567
UD
131 {
132 funlockfile (stream);
133 return NULL;
134 }
845dcb57
UD
135
136 end_ptr = strchr (buffer, '\n');
137 if (end_ptr != NULL) /* chop newline */
fb87ee96 138 {
b0e805fa
MF
139 /* Do not walk past the start of buffer if it's all whitespace. */
140 while (end_ptr != buffer
141 && (end_ptr[-1] == ' ' || end_ptr[-1] == '\t'))
fb87ee96
VN
142 end_ptr--;
143 *end_ptr = '\0';
144 }
845dcb57
UD
145 else
146 {
147 /* Not the whole line was read. Do it now but forget it. */
148 char tmp[1024];
84e5e756 149 while (__fgets_unlocked (tmp, sizeof tmp, stream) != NULL)
845dcb57
UD
150 if (strchr (tmp, '\n') != NULL)
151 break;
152 }
153
154 head = buffer + strspn (buffer, " \t");
155 /* skip empty lines and comment lines: */
b0b422e8
UD
156 }
157 while (head[0] == '\0' || head[0] == '#');
845dcb57 158
b0b422e8
UD
159 cp = __strsep (&head, " \t");
160 mp->mnt_fsname = cp != NULL ? decode_name (cp) : (char *) "";
845dcb57
UD
161 if (head)
162 head += strspn (head, " \t");
b0b422e8
UD
163 cp = __strsep (&head, " \t");
164 mp->mnt_dir = cp != NULL ? decode_name (cp) : (char *) "";
845dcb57
UD
165 if (head)
166 head += strspn (head, " \t");
b0b422e8
UD
167 cp = __strsep (&head, " \t");
168 mp->mnt_type = cp != NULL ? decode_name (cp) : (char *) "";
845dcb57
UD
169 if (head)
170 head += strspn (head, " \t");
b0b422e8
UD
171 cp = __strsep (&head, " \t");
172 mp->mnt_opts = cp != NULL ? decode_name (cp) : (char *) "";
845dcb57
UD
173 switch (head ? sscanf (head, " %d %d ", &mp->mnt_freq, &mp->mnt_passno) : 0)
174 {
175 case 0:
176 mp->mnt_freq = 0;
177 case 1:
178 mp->mnt_passno = 0;
179 case 2:
49f3a758 180 break;
845dcb57 181 }
71412a8c 182 funlockfile (stream);
845dcb57
UD
183
184 return mp;
185}
30917259 186libc_hidden_def (__getmntent_r)
845dcb57
UD
187weak_alias (__getmntent_r, getmntent_r)
188
b0b422e8
UD
189
190/* We have to use an encoding for names if they contain spaces or tabs.
191 To be able to represent all characters we also have to escape the
192 backslash itself. This "function" must be a macro since we use
193 `alloca'. */
194#define encode_name(name) \
195 do { \
196 const char *rp = name; \
197 \
198 while (*rp != '\0') \
ab00f4ea 199 if (*rp == ' ' || *rp == '\t' || *rp == '\n' || *rp == '\\') \
b0b422e8 200 break; \
63f7cb44
UD
201 else \
202 ++rp; \
b0b422e8
UD
203 \
204 if (*rp != '\0') \
205 { \
206 /* In the worst case the length of the string can increase to \
ab00f4ea 207 four times the current length. */ \
63f7cb44 208 char *wp; \
b0b422e8
UD
209 \
210 rp = name; \
63f7cb44
UD
211 name = wp = (char *) alloca (strlen (name) * 4 + 1); \
212 \
b0b422e8
UD
213 do \
214 if (*rp == ' ') \
215 { \
216 *wp++ = '\\'; \
217 *wp++ = '0'; \
218 *wp++ = '4'; \
219 *wp++ = '0'; \
220 } \
221 else if (*rp == '\t') \
e796f92f
UD
222 { \
223 *wp++ = '\\'; \
224 *wp++ = '0'; \
225 *wp++ = '1'; \
226 *wp++ = '1'; \
227 } \
228 else if (*rp == '\n') \
b0b422e8
UD
229 { \
230 *wp++ = '\\'; \
231 *wp++ = '0'; \
232 *wp++ = '1'; \
233 *wp++ = '2'; \
234 } \
235 else if (*rp == '\\') \
236 { \
237 *wp++ = '\\'; \
238 *wp++ = '\\'; \
239 } \
240 else \
241 *wp++ = *rp; \
242 while (*rp++ != '\0'); \
b0b422e8
UD
243 } \
244 } while (0)
245
246
845dcb57
UD
247/* Write the mount table entry described by MNT to STREAM.
248 Return zero on success, nonzero on failure. */
249int
250__addmntent (FILE *stream, const struct mntent *mnt)
251{
b0b422e8 252 struct mntent mntcopy = *mnt;
845dcb57
UD
253 if (fseek (stream, 0, SEEK_END))
254 return 1;
255
b0b422e8
UD
256 /* Encode spaces and tabs in the names. */
257 encode_name (mntcopy.mnt_fsname);
258 encode_name (mntcopy.mnt_dir);
259 encode_name (mntcopy.mnt_type);
260 encode_name (mntcopy.mnt_opts);
261
845dcb57 262 return (fprintf (stream, "%s %s %s %s %d %d\n",
b0b422e8
UD
263 mntcopy.mnt_fsname,
264 mntcopy.mnt_dir,
265 mntcopy.mnt_type,
266 mntcopy.mnt_opts,
267 mntcopy.mnt_freq,
e1fb097f
UD
268 mntcopy.mnt_passno) < 0
269 || fflush (stream) != 0);
845dcb57
UD
270}
271weak_alias (__addmntent, addmntent)
272
273
274/* Search MNT->mnt_opts for an option matching OPT.
275 Returns the address of the substring, or null if none found. */
276char *
277__hasmntopt (const struct mntent *mnt, const char *opt)
278{
279 const size_t optlen = strlen (opt);
280 char *rest = mnt->mnt_opts, *p;
281
282 while ((p = strstr (rest, opt)) != NULL)
283 {
66f17705
UD
284 if ((p == rest || p[-1] == ',')
285 && (p[optlen] == '\0' || p[optlen] == '=' || p[optlen] == ','))
845dcb57
UD
286 return p;
287
66f17705 288 rest = strchr (p, ',');
df4ef2ab
UD
289 if (rest == NULL)
290 break;
291 ++rest;
845dcb57
UD
292 }
293
294 return NULL;
295}
d1903329 296libc_hidden_def (__hasmntopt)
845dcb57 297weak_alias (__hasmntopt, hasmntopt)