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
23 #include <stdio_ext.h>
25 #include <sys/types.h>
28 # define flockfile(s) _IO_flockfile (s)
29 # define funlockfile(s) _IO_funlockfile (s)
36 /* Prepare to begin reading and/or writing mount table entries from the
37 beginning of FILE. MODE is as for `fopen'. */
39 __setmntent (const char *file
, const char *mode
)
41 FILE *result
= fopen (file
, mode
);
44 /* We do the locking ourselves. */
45 __fsetlocking (result
, FSETLOCKING_BYCALLER
);
50 weak_alias (__setmntent
, setmntent
)
53 /* Close a stream opened with `setmntent'. */
55 __endmntent (FILE *stream
)
57 if (stream
) /* SunOS 4.x allows for NULL stream */
59 return 1; /* SunOS 4.x says to always return 1 */
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. */
70 decode_name (char *buf
)
76 if (rp
[0] == '\\' && rp
[1] == '0' && rp
[2] == '4' && rp
[3] == '0')
78 /* \040 is a SPACE. */
82 else if (rp
[0] == '\\' && rp
[1] == '0' && rp
[2] == '1' && rp
[3] == '2')
88 else if (rp
[0] == '\\' && rp
[1] == '\\')
90 /* We have to escape \\ to be able to represent all characters. */
96 while (*rp
++ != '\0');
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
106 __getmntent_r (FILE *stream
, struct mntent
*mp
, char *buffer
, int bufsiz
)
116 if (fgets_unlocked (buffer
, bufsiz
, stream
) == NULL
)
118 funlockfile (stream
);
122 end_ptr
= strchr (buffer
, '\n');
123 if (end_ptr
!= NULL
) /* chop newline */
127 /* Not the whole line was read. Do it now but forget it. */
129 while (fgets_unlocked (tmp
, sizeof tmp
, stream
) != NULL
)
130 if (strchr (tmp
, '\n') != NULL
)
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 *) "";
142 head
+= strspn (head
, " \t");
143 cp
= __strsep (&head
, " \t");
144 mp
->mnt_dir
= cp
!= NULL
? decode_name (cp
) : (char *) "";
146 head
+= strspn (head
, " \t");
147 cp
= __strsep (&head
, " \t");
148 mp
->mnt_type
= cp
!= NULL
? decode_name (cp
) : (char *) "";
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)
162 funlockfile (stream
);
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
174 #define encode_name(name) \
176 const char *rp = name; \
178 while (*rp != '\0') \
179 if (*rp == ' ' || *rp == '\t' || *rp == '\\') \
186 /* In the worst case the length of the string can increase to \
187 founr times the current length. */ \
191 name = wp = (char *) alloca (strlen (name) * 4 + 1); \
201 else if (*rp == '\t') \
208 else if (*rp == '\\') \
215 while (*rp++ != '\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
))
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",
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. */
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
)
259 && (p
[optlen
] == '\0' ||
264 rest
= strchr (rest
, ',');
272 weak_alias (__hasmntopt
, hasmntopt
)