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