]> git.ipfire.org Git - thirdparty/glibc.git/blame - misc/mntent_r.c
Update copyright notices with scripts/update-copyrights
[thirdparty/glibc.git] / misc / mntent_r.c
CommitLineData
845dcb57 1/* Utilities for reading/writing fstab, mtab, etc.
d4697bc9 2 Copyright (C) 1995-2014 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
71412a8c 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 */
138 *end_ptr = '\0';
139 else
140 {
141 /* Not the whole line was read. Do it now but forget it. */
142 char tmp[1024];
71412a8c 143 while (fgets_unlocked (tmp, sizeof tmp, stream) != NULL)
845dcb57
UD
144 if (strchr (tmp, '\n') != NULL)
145 break;
146 }
147
148 head = buffer + strspn (buffer, " \t");
149 /* skip empty lines and comment lines: */
b0b422e8
UD
150 }
151 while (head[0] == '\0' || head[0] == '#');
845dcb57 152
b0b422e8
UD
153 cp = __strsep (&head, " \t");
154 mp->mnt_fsname = cp != NULL ? decode_name (cp) : (char *) "";
845dcb57
UD
155 if (head)
156 head += strspn (head, " \t");
b0b422e8
UD
157 cp = __strsep (&head, " \t");
158 mp->mnt_dir = cp != NULL ? decode_name (cp) : (char *) "";
845dcb57
UD
159 if (head)
160 head += strspn (head, " \t");
b0b422e8
UD
161 cp = __strsep (&head, " \t");
162 mp->mnt_type = cp != NULL ? decode_name (cp) : (char *) "";
845dcb57
UD
163 if (head)
164 head += strspn (head, " \t");
b0b422e8
UD
165 cp = __strsep (&head, " \t");
166 mp->mnt_opts = cp != NULL ? decode_name (cp) : (char *) "";
845dcb57
UD
167 switch (head ? sscanf (head, " %d %d ", &mp->mnt_freq, &mp->mnt_passno) : 0)
168 {
169 case 0:
170 mp->mnt_freq = 0;
171 case 1:
172 mp->mnt_passno = 0;
173 case 2:
49f3a758 174 break;
845dcb57 175 }
71412a8c 176 funlockfile (stream);
845dcb57
UD
177
178 return mp;
179}
30917259 180libc_hidden_def (__getmntent_r)
845dcb57
UD
181weak_alias (__getmntent_r, getmntent_r)
182
b0b422e8
UD
183
184/* We have to use an encoding for names if they contain spaces or tabs.
185 To be able to represent all characters we also have to escape the
186 backslash itself. This "function" must be a macro since we use
187 `alloca'. */
188#define encode_name(name) \
189 do { \
190 const char *rp = name; \
191 \
192 while (*rp != '\0') \
ab00f4ea 193 if (*rp == ' ' || *rp == '\t' || *rp == '\n' || *rp == '\\') \
b0b422e8 194 break; \
63f7cb44
UD
195 else \
196 ++rp; \
b0b422e8
UD
197 \
198 if (*rp != '\0') \
199 { \
200 /* In the worst case the length of the string can increase to \
ab00f4ea 201 four times the current length. */ \
63f7cb44 202 char *wp; \
b0b422e8
UD
203 \
204 rp = name; \
63f7cb44
UD
205 name = wp = (char *) alloca (strlen (name) * 4 + 1); \
206 \
b0b422e8
UD
207 do \
208 if (*rp == ' ') \
209 { \
210 *wp++ = '\\'; \
211 *wp++ = '0'; \
212 *wp++ = '4'; \
213 *wp++ = '0'; \
214 } \
215 else if (*rp == '\t') \
e796f92f
UD
216 { \
217 *wp++ = '\\'; \
218 *wp++ = '0'; \
219 *wp++ = '1'; \
220 *wp++ = '1'; \
221 } \
222 else if (*rp == '\n') \
b0b422e8
UD
223 { \
224 *wp++ = '\\'; \
225 *wp++ = '0'; \
226 *wp++ = '1'; \
227 *wp++ = '2'; \
228 } \
229 else if (*rp == '\\') \
230 { \
231 *wp++ = '\\'; \
232 *wp++ = '\\'; \
233 } \
234 else \
235 *wp++ = *rp; \
236 while (*rp++ != '\0'); \
b0b422e8
UD
237 } \
238 } while (0)
239
240
845dcb57
UD
241/* Write the mount table entry described by MNT to STREAM.
242 Return zero on success, nonzero on failure. */
243int
244__addmntent (FILE *stream, const struct mntent *mnt)
245{
b0b422e8 246 struct mntent mntcopy = *mnt;
845dcb57
UD
247 if (fseek (stream, 0, SEEK_END))
248 return 1;
249
b0b422e8
UD
250 /* Encode spaces and tabs in the names. */
251 encode_name (mntcopy.mnt_fsname);
252 encode_name (mntcopy.mnt_dir);
253 encode_name (mntcopy.mnt_type);
254 encode_name (mntcopy.mnt_opts);
255
845dcb57 256 return (fprintf (stream, "%s %s %s %s %d %d\n",
b0b422e8
UD
257 mntcopy.mnt_fsname,
258 mntcopy.mnt_dir,
259 mntcopy.mnt_type,
260 mntcopy.mnt_opts,
261 mntcopy.mnt_freq,
e1fb097f
UD
262 mntcopy.mnt_passno) < 0
263 || fflush (stream) != 0);
845dcb57
UD
264}
265weak_alias (__addmntent, addmntent)
266
267
268/* Search MNT->mnt_opts for an option matching OPT.
269 Returns the address of the substring, or null if none found. */
270char *
271__hasmntopt (const struct mntent *mnt, const char *opt)
272{
273 const size_t optlen = strlen (opt);
274 char *rest = mnt->mnt_opts, *p;
275
276 while ((p = strstr (rest, opt)) != NULL)
277 {
66f17705
UD
278 if ((p == rest || p[-1] == ',')
279 && (p[optlen] == '\0' || p[optlen] == '=' || p[optlen] == ','))
845dcb57
UD
280 return p;
281
66f17705 282 rest = strchr (p, ',');
df4ef2ab
UD
283 if (rest == NULL)
284 break;
285 ++rest;
845dcb57
UD
286 }
287
288 return NULL;
289}
290weak_alias (__hasmntopt, hasmntopt)