summaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-07-26 01:16:48 +0000
committerUlrich Drepper <drepper@redhat.com>1999-07-26 01:16:48 +0000
commitb0b422e85da7e35cc989d177445912383fb7eda1 (patch)
tree91fc0198e8d9cd60800f1408d46b261480439962 /misc
parent722c33bbb6d2984cf537f0d3669617fba041fb50 (diff)
downloadglibc-b0b422e85da7e35cc989d177445912383fb7eda1.tar.gz
Update.
* misc/mntent_r.c: Allow spaces and tabs in entry names by encoding these characters.
Diffstat (limited to 'misc')
-rw-r--r--misc/mntent_r.c123
1 files changed, 111 insertions, 12 deletions
diff --git a/misc/mntent_r.c b/misc/mntent_r.c
index f6ee1ca64e..43cb3f732a 100644
--- a/misc/mntent_r.c
+++ b/misc/mntent_r.c
@@ -1,5 +1,5 @@
/* Utilities for reading/writing fstab, mtab, etc.
- Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -48,12 +48,50 @@ __endmntent (FILE *stream)
weak_alias (__endmntent, endmntent)
+/* Since the values in a line are separated by spaces, a name cannot
+ contain a space. Therefore some programs encode spaces in names
+ by the strings "\040". We undo the encoding when reading an entry.
+ The decoding happens in place. */
+static char *
+decode_name (char *buf)
+{
+ char *rp = buf;
+ char *wp = buf;
+
+ do
+ if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '4' && rp[3] == '0')
+ {
+ /* \040 is a SPACE. */
+ *wp++ = ' ';
+ rp += 3;
+ }
+ else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '2')
+ {
+ /* \012 is a TAB. */
+ *wp++ = '\t';
+ rp += 3;
+ }
+ else if (rp[0] == '\\' && rp[1] == '\\')
+ {
+ /* We have to escape \\ to be able to represent all characters. */
+ *wp++ = '\\';
+ rp += 1;
+ }
+ else
+ *wp++ = *rp;
+ while (*rp++ != '\0');
+
+ return buf;
+}
+
+
/* Read one mount table entry from STREAM. Returns a pointer to storage
reused on the next call, or null for EOF or error (use feof/ferror to
check). */
struct mntent *
__getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
{
+ char *cp;
char *head;
flockfile (stream);
@@ -81,18 +119,23 @@ __getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
head = buffer + strspn (buffer, " \t");
/* skip empty lines and comment lines: */
- } while (head[0] == '\0' || head[0] == '#');
+ }
+ while (head[0] == '\0' || head[0] == '#');
- mp->mnt_fsname = __strsep (&head, " \t") ?: (char *) "";
+ cp = __strsep (&head, " \t");
+ mp->mnt_fsname = cp != NULL ? decode_name (cp) : (char *) "";
if (head)
head += strspn (head, " \t");
- mp->mnt_dir = __strsep (&head, " \t") ?: (char *) "";
+ cp = __strsep (&head, " \t");
+ mp->mnt_dir = cp != NULL ? decode_name (cp) : (char *) "";
if (head)
head += strspn (head, " \t");
- mp->mnt_type = __strsep (&head, " \t") ?: (char *) "";
+ cp = __strsep (&head, " \t");
+ mp->mnt_type = cp != NULL ? decode_name (cp) : (char *) "";
if (head)
head += strspn (head, " \t");
- mp->mnt_opts = __strsep (&head, " \t") ?: (char *) "";
+ cp = __strsep (&head, " \t");
+ mp->mnt_opts = cp != NULL ? decode_name (cp) : (char *) "";
switch (head ? sscanf (head, " %d %d ", &mp->mnt_freq, &mp->mnt_passno) : 0)
{
case 0:
@@ -107,21 +150,77 @@ __getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
}
weak_alias (__getmntent_r, getmntent_r)
+
+/* We have to use an encoding for names if they contain spaces or tabs.
+ To be able to represent all characters we also have to escape the
+ backslash itself. This "function" must be a macro since we use
+ `alloca'. */
+#define encode_name(name) \
+ do { \
+ const char *rp = name; \
+ \
+ while (*rp != '\0') \
+ if (*rp == ' ' || *rp == '\t' || *rp == '\\') \
+ break; \
+ \
+ if (*rp != '\0') \
+ { \
+ /* In the worst case the length of the string can increase to \
+ founr times the current length. */ \
+ char *wp = (char *) alloca (strlen (name) * 4 + 1); \
+ \
+ rp = name; \
+ do \
+ if (*rp == ' ') \
+ { \
+ *wp++ = '\\'; \
+ *wp++ = '0'; \
+ *wp++ = '4'; \
+ *wp++ = '0'; \
+ } \
+ else if (*rp == '\t') \
+ { \
+ *wp++ = '\\'; \
+ *wp++ = '0'; \
+ *wp++ = '1'; \
+ *wp++ = '2'; \
+ } \
+ else if (*rp == '\\') \
+ { \
+ *wp++ = '\\'; \
+ *wp++ = '\\'; \
+ } \
+ else \
+ *wp++ = *rp; \
+ while (*rp++ != '\0'); \
+ \
+ name = wp; \
+ } \
+ } while (0)
+
+
/* Write the mount table entry described by MNT to STREAM.
Return zero on success, nonzero on failure. */
int
__addmntent (FILE *stream, const struct mntent *mnt)
{
+ struct mntent mntcopy = *mnt;
if (fseek (stream, 0, SEEK_END))
return 1;
+ /* Encode spaces and tabs in the names. */
+ encode_name (mntcopy.mnt_fsname);
+ encode_name (mntcopy.mnt_dir);
+ encode_name (mntcopy.mnt_type);
+ encode_name (mntcopy.mnt_opts);
+
return (fprintf (stream, "%s %s %s %s %d %d\n",
- mnt->mnt_fsname,
- mnt->mnt_dir,
- mnt->mnt_type,
- mnt->mnt_opts,
- mnt->mnt_freq,
- mnt->mnt_passno)
+ mntcopy.mnt_fsname,
+ mntcopy.mnt_dir,
+ mntcopy.mnt_type,
+ mntcopy.mnt_opts,
+ mntcopy.mnt_freq,
+ mntcopy.mnt_passno)
< 0 ? 1 : 0);
}
weak_alias (__addmntent, addmntent)