diff options
Diffstat (limited to 'misc/mntent_r.c')
-rw-r--r-- | misc/mntent_r.c | 123 |
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) |