Update.
[glibc.git] / misc / mntent_r.c
blob7a394186d489cc3a2598bf1c6b38c33b398aa50b
1 /* Utilities for reading/writing fstab, mtab, etc.
2 Copyright (C) 1995-2000, 2001, 2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
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.
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
13 Lesser General Public License for more details.
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. */
20 #include <alloca.h>
21 #include <mntent.h>
22 #include <stdio.h>
23 #include <stdio_ext.h>
24 #include <string.h>
25 #include <sys/types.h>
27 #ifdef USE_IN_LIBIO
28 # define flockfile(s) _IO_flockfile (s)
29 # define funlockfile(s) _IO_funlockfile (s)
30 #endif
32 #undef __setmntent
33 #undef __endmntent
34 #undef __getmntent_r
36 /* Prepare to begin reading and/or writing mount table entries from the
37 beginning of FILE. MODE is as for `fopen'. */
38 FILE *
39 __setmntent (const char *file, const char *mode)
41 FILE *result = fopen (file, mode);
43 if (result != NULL)
44 /* We do the locking ourselves. */
45 __fsetlocking (result, FSETLOCKING_BYCALLER);
47 return result;
49 INTDEF(__setmntent)
50 weak_alias (__setmntent, setmntent)
53 /* Close a stream opened with `setmntent'. */
54 int
55 __endmntent (FILE *stream)
57 if (stream) /* SunOS 4.x allows for NULL stream */
58 fclose (stream);
59 return 1; /* SunOS 4.x says to always return 1 */
61 INTDEF(__endmntent)
62 weak_alias (__endmntent, endmntent)
65 /* Since the values in a line are separated by spaces, a name cannot
66 contain a space. Therefore some programs encode spaces in names
67 by the strings "\040". We undo the encoding when reading an entry.
68 The decoding happens in place. */
69 static char *
70 decode_name (char *buf)
72 char *rp = buf;
73 char *wp = buf;
76 if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '4' && rp[3] == '0')
78 /* \040 is a SPACE. */
79 *wp++ = ' ';
80 rp += 3;
82 else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '2')
84 /* \012 is a TAB. */
85 *wp++ = '\t';
86 rp += 3;
88 else if (rp[0] == '\\' && rp[1] == '\\')
90 /* We have to escape \\ to be able to represent all characters. */
91 *wp++ = '\\';
92 rp += 1;
94 else
95 *wp++ = *rp;
96 while (*rp++ != '\0');
98 return buf;
102 /* Read one mount table entry from STREAM. Returns a pointer to storage
103 reused on the next call, or null for EOF or error (use feof/ferror to
104 check). */
105 struct mntent *
106 __getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
108 char *cp;
109 char *head;
111 flockfile (stream);
114 char *end_ptr;
116 if (fgets_unlocked (buffer, bufsiz, stream) == NULL)
118 funlockfile (stream);
119 return NULL;
122 end_ptr = strchr (buffer, '\n');
123 if (end_ptr != NULL) /* chop newline */
124 *end_ptr = '\0';
125 else
127 /* Not the whole line was read. Do it now but forget it. */
128 char tmp[1024];
129 while (fgets_unlocked (tmp, sizeof tmp, stream) != NULL)
130 if (strchr (tmp, '\n') != NULL)
131 break;
134 head = buffer + strspn (buffer, " \t");
135 /* skip empty lines and comment lines: */
137 while (head[0] == '\0' || head[0] == '#');
139 cp = __strsep (&head, " \t");
140 mp->mnt_fsname = cp != NULL ? decode_name (cp) : (char *) "";
141 if (head)
142 head += strspn (head, " \t");
143 cp = __strsep (&head, " \t");
144 mp->mnt_dir = cp != NULL ? decode_name (cp) : (char *) "";
145 if (head)
146 head += strspn (head, " \t");
147 cp = __strsep (&head, " \t");
148 mp->mnt_type = cp != NULL ? decode_name (cp) : (char *) "";
149 if (head)
150 head += strspn (head, " \t");
151 cp = __strsep (&head, " \t");
152 mp->mnt_opts = cp != NULL ? decode_name (cp) : (char *) "";
153 switch (head ? sscanf (head, " %d %d ", &mp->mnt_freq, &mp->mnt_passno) : 0)
155 case 0:
156 mp->mnt_freq = 0;
157 case 1:
158 mp->mnt_passno = 0;
159 case 2:
160 break;
162 funlockfile (stream);
164 return mp;
166 INTDEF(__getmntent_r)
167 weak_alias (__getmntent_r, getmntent_r)
170 /* We have to use an encoding for names if they contain spaces or tabs.
171 To be able to represent all characters we also have to escape the
172 backslash itself. This "function" must be a macro since we use
173 `alloca'. */
174 #define encode_name(name) \
175 do { \
176 const char *rp = name; \
178 while (*rp != '\0') \
179 if (*rp == ' ' || *rp == '\t' || *rp == '\\') \
180 break; \
181 else \
182 ++rp; \
184 if (*rp != '\0') \
186 /* In the worst case the length of the string can increase to \
187 founr times the current length. */ \
188 char *wp; \
190 rp = name; \
191 name = wp = (char *) alloca (strlen (name) * 4 + 1); \
193 do \
194 if (*rp == ' ') \
196 *wp++ = '\\'; \
197 *wp++ = '0'; \
198 *wp++ = '4'; \
199 *wp++ = '0'; \
201 else if (*rp == '\t') \
203 *wp++ = '\\'; \
204 *wp++ = '0'; \
205 *wp++ = '1'; \
206 *wp++ = '2'; \
208 else if (*rp == '\\') \
210 *wp++ = '\\'; \
211 *wp++ = '\\'; \
213 else \
214 *wp++ = *rp; \
215 while (*rp++ != '\0'); \
217 } while (0)
220 /* Write the mount table entry described by MNT to STREAM.
221 Return zero on success, nonzero on failure. */
223 __addmntent (FILE *stream, const struct mntent *mnt)
225 struct mntent mntcopy = *mnt;
226 if (fseek (stream, 0, SEEK_END))
227 return 1;
229 /* Encode spaces and tabs in the names. */
230 encode_name (mntcopy.mnt_fsname);
231 encode_name (mntcopy.mnt_dir);
232 encode_name (mntcopy.mnt_type);
233 encode_name (mntcopy.mnt_opts);
235 return (fprintf (stream, "%s %s %s %s %d %d\n",
236 mntcopy.mnt_fsname,
237 mntcopy.mnt_dir,
238 mntcopy.mnt_type,
239 mntcopy.mnt_opts,
240 mntcopy.mnt_freq,
241 mntcopy.mnt_passno)
242 < 0 ? 1 : 0);
244 weak_alias (__addmntent, addmntent)
247 /* Search MNT->mnt_opts for an option matching OPT.
248 Returns the address of the substring, or null if none found. */
249 char *
250 __hasmntopt (const struct mntent *mnt, const char *opt)
252 const size_t optlen = strlen (opt);
253 char *rest = mnt->mnt_opts, *p;
255 while ((p = strstr (rest, opt)) != NULL)
257 if (p == rest
258 || (p[-1] == ','
259 && (p[optlen] == '\0' ||
260 p[optlen] == '=' ||
261 p[optlen] == ',')))
262 return p;
264 rest = strchr (rest, ',');
265 if (rest == NULL)
266 break;
267 ++rest;
270 return NULL;
272 weak_alias (__hasmntopt, hasmntopt)