Update.
[glibc.git] / misc / mntent_r.c
blob1a87105657aad458c760ae5621fd421a3fd36537
1 /* Utilities for reading/writing fstab, mtab, etc.
2 Copyright (C) 1995-2000, 2001 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 /* Prepare to begin reading and/or writing mount table entries from the
33 beginning of FILE. MODE is as for `fopen'. */
34 FILE *
35 __setmntent (const char *file, const char *mode)
37 FILE *result = fopen (file, mode);
39 if (result != NULL)
40 /* We do the locking ourselves. */
41 __fsetlocking (result, FSETLOCKING_BYCALLER);
43 return result;
45 weak_alias (__setmntent, setmntent)
48 /* Close a stream opened with `setmntent'. */
49 int
50 __endmntent (FILE *stream)
52 if (stream) /* SunOS 4.x allows for NULL stream */
53 fclose (stream);
54 return 1; /* SunOS 4.x says to always return 1 */
56 weak_alias (__endmntent, endmntent)
59 /* Since the values in a line are separated by spaces, a name cannot
60 contain a space. Therefore some programs encode spaces in names
61 by the strings "\040". We undo the encoding when reading an entry.
62 The decoding happens in place. */
63 static char *
64 decode_name (char *buf)
66 char *rp = buf;
67 char *wp = buf;
70 if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '4' && rp[3] == '0')
72 /* \040 is a SPACE. */
73 *wp++ = ' ';
74 rp += 3;
76 else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '2')
78 /* \012 is a TAB. */
79 *wp++ = '\t';
80 rp += 3;
82 else if (rp[0] == '\\' && rp[1] == '\\')
84 /* We have to escape \\ to be able to represent all characters. */
85 *wp++ = '\\';
86 rp += 1;
88 else
89 *wp++ = *rp;
90 while (*rp++ != '\0');
92 return buf;
96 /* Read one mount table entry from STREAM. Returns a pointer to storage
97 reused on the next call, or null for EOF or error (use feof/ferror to
98 check). */
99 struct mntent *
100 __getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
102 char *cp;
103 char *head;
105 flockfile (stream);
108 char *end_ptr;
110 if (fgets_unlocked (buffer, bufsiz, stream) == NULL)
112 funlockfile (stream);
113 return NULL;
116 end_ptr = strchr (buffer, '\n');
117 if (end_ptr != NULL) /* chop newline */
118 *end_ptr = '\0';
119 else
121 /* Not the whole line was read. Do it now but forget it. */
122 char tmp[1024];
123 while (fgets_unlocked (tmp, sizeof tmp, stream) != NULL)
124 if (strchr (tmp, '\n') != NULL)
125 break;
128 head = buffer + strspn (buffer, " \t");
129 /* skip empty lines and comment lines: */
131 while (head[0] == '\0' || head[0] == '#');
133 cp = __strsep (&head, " \t");
134 mp->mnt_fsname = cp != NULL ? decode_name (cp) : (char *) "";
135 if (head)
136 head += strspn (head, " \t");
137 cp = __strsep (&head, " \t");
138 mp->mnt_dir = cp != NULL ? decode_name (cp) : (char *) "";
139 if (head)
140 head += strspn (head, " \t");
141 cp = __strsep (&head, " \t");
142 mp->mnt_type = cp != NULL ? decode_name (cp) : (char *) "";
143 if (head)
144 head += strspn (head, " \t");
145 cp = __strsep (&head, " \t");
146 mp->mnt_opts = cp != NULL ? decode_name (cp) : (char *) "";
147 switch (head ? sscanf (head, " %d %d ", &mp->mnt_freq, &mp->mnt_passno) : 0)
149 case 0:
150 mp->mnt_freq = 0;
151 case 1:
152 mp->mnt_passno = 0;
153 case 2:
154 break;
156 funlockfile (stream);
158 return mp;
160 weak_alias (__getmntent_r, getmntent_r)
163 /* We have to use an encoding for names if they contain spaces or tabs.
164 To be able to represent all characters we also have to escape the
165 backslash itself. This "function" must be a macro since we use
166 `alloca'. */
167 #define encode_name(name) \
168 do { \
169 const char *rp = name; \
171 while (*rp != '\0') \
172 if (*rp == ' ' || *rp == '\t' || *rp == '\\') \
173 break; \
174 else \
175 ++rp; \
177 if (*rp != '\0') \
179 /* In the worst case the length of the string can increase to \
180 founr times the current length. */ \
181 char *wp; \
183 rp = name; \
184 name = wp = (char *) alloca (strlen (name) * 4 + 1); \
186 do \
187 if (*rp == ' ') \
189 *wp++ = '\\'; \
190 *wp++ = '0'; \
191 *wp++ = '4'; \
192 *wp++ = '0'; \
194 else if (*rp == '\t') \
196 *wp++ = '\\'; \
197 *wp++ = '0'; \
198 *wp++ = '1'; \
199 *wp++ = '2'; \
201 else if (*rp == '\\') \
203 *wp++ = '\\'; \
204 *wp++ = '\\'; \
206 else \
207 *wp++ = *rp; \
208 while (*rp++ != '\0'); \
210 } while (0)
213 /* Write the mount table entry described by MNT to STREAM.
214 Return zero on success, nonzero on failure. */
216 __addmntent (FILE *stream, const struct mntent *mnt)
218 struct mntent mntcopy = *mnt;
219 if (fseek (stream, 0, SEEK_END))
220 return 1;
222 /* Encode spaces and tabs in the names. */
223 encode_name (mntcopy.mnt_fsname);
224 encode_name (mntcopy.mnt_dir);
225 encode_name (mntcopy.mnt_type);
226 encode_name (mntcopy.mnt_opts);
228 return (fprintf (stream, "%s %s %s %s %d %d\n",
229 mntcopy.mnt_fsname,
230 mntcopy.mnt_dir,
231 mntcopy.mnt_type,
232 mntcopy.mnt_opts,
233 mntcopy.mnt_freq,
234 mntcopy.mnt_passno)
235 < 0 ? 1 : 0);
237 weak_alias (__addmntent, addmntent)
240 /* Search MNT->mnt_opts for an option matching OPT.
241 Returns the address of the substring, or null if none found. */
242 char *
243 __hasmntopt (const struct mntent *mnt, const char *opt)
245 const size_t optlen = strlen (opt);
246 char *rest = mnt->mnt_opts, *p;
248 while ((p = strstr (rest, opt)) != NULL)
250 if (p == rest
251 || (p[-1] == ','
252 && (p[optlen] == '\0' ||
253 p[optlen] == '=' ||
254 p[optlen] == ',')))
255 return p;
257 rest = strchr (rest, ',');
258 if (rest == NULL)
259 break;
260 ++rest;
263 return NULL;
265 weak_alias (__hasmntopt, hasmntopt)