Blame misc/mntent_r.c

Packit Service 82fcde
/* Utilities for reading/writing fstab, mtab, etc.
Packit Service 82fcde
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <alloca.h>
Packit Service 82fcde
#include <mntent.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <stdio_ext.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <sys/types.h>
Packit Service 82fcde
Packit Service 82fcde
#define flockfile(s) _IO_flockfile (s)
Packit Service 82fcde
#define funlockfile(s) _IO_funlockfile (s)
Packit Service 82fcde
Packit Service 82fcde
#undef __setmntent
Packit Service 82fcde
#undef __endmntent
Packit Service 82fcde
#undef __getmntent_r
Packit Service 82fcde
Packit Service 82fcde
/* Prepare to begin reading and/or writing mount table entries from the
Packit Service 82fcde
   beginning of FILE.  MODE is as for `fopen'.  */
Packit Service 82fcde
FILE *
Packit Service 82fcde
__setmntent (const char *file, const char *mode)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Extend the mode parameter with "c" to disable cancellation in the
Packit Service 82fcde
     I/O functions and "e" to set FD_CLOEXEC.  */
Packit Service 82fcde
  size_t modelen = strlen (mode);
Packit Service 82fcde
  char newmode[modelen + 3];
Packit Service 82fcde
  memcpy (mempcpy (newmode, mode, modelen), "ce", 3);
Packit Service 82fcde
  FILE *result = fopen (file, newmode);
Packit Service 82fcde
Packit Service 82fcde
  if (result != NULL)
Packit Service 82fcde
    /* We do the locking ourselves.  */
Packit Service 82fcde
    __fsetlocking (result, FSETLOCKING_BYCALLER);
Packit Service 82fcde
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (__setmntent)
Packit Service 82fcde
weak_alias (__setmntent, setmntent)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Close a stream opened with `setmntent'.  */
Packit Service 82fcde
int
Packit Service 82fcde
__endmntent (FILE *stream)
Packit Service 82fcde
{
Packit Service 82fcde
  if (stream)		/* SunOS 4.x allows for NULL stream */
Packit Service 82fcde
    fclose (stream);
Packit Service 82fcde
  return 1;		/* SunOS 4.x says to always return 1 */
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (__endmntent)
Packit Service 82fcde
weak_alias (__endmntent, endmntent)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Since the values in a line are separated by spaces, a name cannot
Packit Service 82fcde
   contain a space.  Therefore some programs encode spaces in names
Packit Service 82fcde
   by the strings "\040".  We undo the encoding when reading an entry.
Packit Service 82fcde
   The decoding happens in place.  */
Packit Service 82fcde
static char *
Packit Service 82fcde
decode_name (char *buf)
Packit Service 82fcde
{
Packit Service 82fcde
  char *rp = buf;
Packit Service 82fcde
  char *wp = buf;
Packit Service 82fcde
Packit Service 82fcde
  do
Packit Service 82fcde
    if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '4' && rp[3] == '0')
Packit Service 82fcde
      {
Packit Service 82fcde
	/* \040 is a SPACE.  */
Packit Service 82fcde
	*wp++ = ' ';
Packit Service 82fcde
	rp += 3;
Packit Service 82fcde
      }
Packit Service 82fcde
    else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '1')
Packit Service 82fcde
      {
Packit Service 82fcde
	/* \011 is a TAB.  */
Packit Service 82fcde
	*wp++ = '\t';
Packit Service 82fcde
	rp += 3;
Packit Service 82fcde
      }
Packit Service 82fcde
    else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '2')
Packit Service 82fcde
      {
Packit Service 82fcde
	/* \012 is a NEWLINE.  */
Packit Service 82fcde
	*wp++ = '\n';
Packit Service 82fcde
	rp += 3;
Packit Service 82fcde
      }
Packit Service 82fcde
    else if (rp[0] == '\\' && rp[1] == '\\')
Packit Service 82fcde
      {
Packit Service 82fcde
	/* We have to escape \\ to be able to represent all characters.  */
Packit Service 82fcde
	*wp++ = '\\';
Packit Service 82fcde
	rp += 1;
Packit Service 82fcde
      }
Packit Service 82fcde
    else if (rp[0] == '\\' && rp[1] == '1' && rp[2] == '3' && rp[3] == '4')
Packit Service 82fcde
      {
Packit Service 82fcde
	/* \134 is also \\.  */
Packit Service 82fcde
	*wp++ = '\\';
Packit Service 82fcde
	rp += 3;
Packit Service 82fcde
      }
Packit Service 82fcde
    else
Packit Service 82fcde
      *wp++ = *rp;
Packit Service 82fcde
  while (*rp++ != '\0');
Packit Service 82fcde
Packit Service 82fcde
  return buf;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 1c5418
Packit Service 1c5418
/* Read one mount table entry from STREAM.  Returns a pointer to storage
Packit Service 1c5418
   reused on the next call, or null for EOF or error (use feof/ferror to
Packit Service 1c5418
   check).  */
Packit Service 1c5418
struct mntent *
Packit Service 1c5418
__getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
Packit Service 82fcde
{
Packit Service 82fcde
  char *cp;
Packit Service 82fcde
  char *head;
Packit Service 82fcde
Packit Service 1c5418
  flockfile (stream);
Packit Service 82fcde
  do
Packit Service 82fcde
    {
Packit Service 82fcde
      char *end_ptr;
Packit Service 82fcde
Packit Service 82fcde
      if (__fgets_unlocked (buffer, bufsiz, stream) == NULL)
Packit Service 1c5418
	{
Packit Service 1c5418
	  funlockfile (stream);
Packit Service 1c5418
	  return NULL;
Packit Service 1c5418
	}
Packit Service 82fcde
Packit Service 82fcde
      end_ptr = strchr (buffer, '\n');
Packit Service 82fcde
      if (end_ptr != NULL)	/* chop newline */
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Do not walk past the start of buffer if it's all whitespace.  */
Packit Service 82fcde
	  while (end_ptr != buffer
Packit Service 82fcde
		 && (end_ptr[-1] == ' ' || end_ptr[-1] == '\t'))
Packit Service 82fcde
            end_ptr--;
Packit Service 82fcde
	  *end_ptr = '\0';
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Not the whole line was read.  Do it now but forget it.  */
Packit Service 82fcde
	  char tmp[1024];
Packit Service 82fcde
	  while (__fgets_unlocked (tmp, sizeof tmp, stream) != NULL)
Packit Service 82fcde
	    if (strchr (tmp, '\n') != NULL)
Packit Service 82fcde
	      break;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      head = buffer + strspn (buffer, " \t");
Packit Service 82fcde
      /* skip empty lines and comment lines:  */
Packit Service 82fcde
    }
Packit Service 82fcde
  while (head[0] == '\0' || head[0] == '#');
Packit Service 82fcde
Packit Service 82fcde
  cp = __strsep (&head, " \t");
Packit Service 82fcde
  mp->mnt_fsname = cp != NULL ? decode_name (cp) : (char *) "";
Packit Service 82fcde
  if (head)
Packit Service 82fcde
    head += strspn (head, " \t");
Packit Service 82fcde
  cp = __strsep (&head, " \t");
Packit Service 82fcde
  mp->mnt_dir = cp != NULL ? decode_name (cp) : (char *) "";
Packit Service 82fcde
  if (head)
Packit Service 82fcde
    head += strspn (head, " \t");
Packit Service 82fcde
  cp = __strsep (&head, " \t");
Packit Service 82fcde
  mp->mnt_type = cp != NULL ? decode_name (cp) : (char *) "";
Packit Service 82fcde
  if (head)
Packit Service 82fcde
    head += strspn (head, " \t");
Packit Service 82fcde
  cp = __strsep (&head, " \t");
Packit Service 82fcde
  mp->mnt_opts = cp != NULL ? decode_name (cp) : (char *) "";
Packit Service 82fcde
  switch (head ? sscanf (head, " %d %d ", &mp->mnt_freq, &mp->mnt_passno) : 0)
Packit Service 82fcde
    {
Packit Service 82fcde
    case 0:
Packit Service 82fcde
      mp->mnt_freq = 0;
Packit Service 82fcde
    case 1:
Packit Service 82fcde
      mp->mnt_passno = 0;
Packit Service 82fcde
    case 2:
Packit Service 82fcde
      break;
Packit Service 82fcde
    }
Packit Service 82fcde
  funlockfile (stream);
Packit Service 82fcde
Packit Service 1c5418
  return mp;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (__getmntent_r)
Packit Service 82fcde
weak_alias (__getmntent_r, getmntent_r)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* We have to use an encoding for names if they contain spaces or tabs.
Packit Service 82fcde
   To be able to represent all characters we also have to escape the
Packit Service 82fcde
   backslash itself.  This "function" must be a macro since we use
Packit Service 82fcde
   `alloca'.  */
Packit Service 82fcde
#define encode_name(name) \
Packit Service 82fcde
  do {									      \
Packit Service 82fcde
    const char *rp = name;						      \
Packit Service 82fcde
									      \
Packit Service 82fcde
    while (*rp != '\0')							      \
Packit Service 82fcde
      if (*rp == ' ' || *rp == '\t' || *rp == '\n' || *rp == '\\')	      \
Packit Service 82fcde
	break;								      \
Packit Service 82fcde
      else								      \
Packit Service 82fcde
	++rp;								      \
Packit Service 82fcde
									      \
Packit Service 82fcde
    if (*rp != '\0')							      \
Packit Service 82fcde
      {									      \
Packit Service 82fcde
	/* In the worst case the length of the string can increase to	      \
Packit Service 82fcde
	   four times the current length.  */				      \
Packit Service 82fcde
	char *wp;							      \
Packit Service 82fcde
									      \
Packit Service 82fcde
	rp = name;							      \
Packit Service 82fcde
	name = wp = (char *) alloca (strlen (name) * 4 + 1);		      \
Packit Service 82fcde
									      \
Packit Service 82fcde
	do								      \
Packit Service 82fcde
	  if (*rp == ' ')						      \
Packit Service 82fcde
	    {								      \
Packit Service 82fcde
	      *wp++ = '\\';						      \
Packit Service 82fcde
	      *wp++ = '0';						      \
Packit Service 82fcde
	      *wp++ = '4';						      \
Packit Service 82fcde
	      *wp++ = '0';						      \
Packit Service 82fcde
	    }								      \
Packit Service 82fcde
	  else if (*rp == '\t')						      \
Packit Service 82fcde
	    {								      \
Packit Service 82fcde
	      *wp++ = '\\';						      \
Packit Service 82fcde
	      *wp++ = '0';						      \
Packit Service 82fcde
	      *wp++ = '1';						      \
Packit Service 82fcde
	      *wp++ = '1';						      \
Packit Service 82fcde
	    }								      \
Packit Service 82fcde
	  else if (*rp == '\n')						      \
Packit Service 82fcde
	    {								      \
Packit Service 82fcde
	      *wp++ = '\\';						      \
Packit Service 82fcde
	      *wp++ = '0';						      \
Packit Service 82fcde
	      *wp++ = '1';						      \
Packit Service 82fcde
	      *wp++ = '2';						      \
Packit Service 82fcde
	    }								      \
Packit Service 82fcde
	  else if (*rp == '\\')						      \
Packit Service 82fcde
	    {								      \
Packit Service 82fcde
	      *wp++ = '\\';						      \
Packit Service 82fcde
	      *wp++ = '\\';						      \
Packit Service 82fcde
	    }								      \
Packit Service 82fcde
	  else								      \
Packit Service 82fcde
	    *wp++ = *rp;						      \
Packit Service 82fcde
	while (*rp++ != '\0');						      \
Packit Service 82fcde
      }									      \
Packit Service 82fcde
  } while (0)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Write the mount table entry described by MNT to STREAM.
Packit Service 82fcde
   Return zero on success, nonzero on failure.  */
Packit Service 82fcde
int
Packit Service 82fcde
__addmntent (FILE *stream, const struct mntent *mnt)
Packit Service 82fcde
{
Packit Service 82fcde
  struct mntent mntcopy = *mnt;
Packit Service 82fcde
  if (fseek (stream, 0, SEEK_END))
Packit Service 82fcde
    return 1;
Packit Service 82fcde
Packit Service 82fcde
  /* Encode spaces and tabs in the names.  */
Packit Service 82fcde
  encode_name (mntcopy.mnt_fsname);
Packit Service 82fcde
  encode_name (mntcopy.mnt_dir);
Packit Service 82fcde
  encode_name (mntcopy.mnt_type);
Packit Service 82fcde
  encode_name (mntcopy.mnt_opts);
Packit Service 82fcde
Packit Service 82fcde
  return (fprintf (stream, "%s %s %s %s %d %d\n",
Packit Service 82fcde
		   mntcopy.mnt_fsname,
Packit Service 82fcde
		   mntcopy.mnt_dir,
Packit Service 82fcde
		   mntcopy.mnt_type,
Packit Service 82fcde
		   mntcopy.mnt_opts,
Packit Service 82fcde
		   mntcopy.mnt_freq,
Packit Service 82fcde
		   mntcopy.mnt_passno) < 0
Packit Service 82fcde
	  || fflush (stream) != 0);
Packit Service 82fcde
}
Packit Service 82fcde
weak_alias (__addmntent, addmntent)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Search MNT->mnt_opts for an option matching OPT.
Packit Service 82fcde
   Returns the address of the substring, or null if none found.  */
Packit Service 82fcde
char *
Packit Service 82fcde
__hasmntopt (const struct mntent *mnt, const char *opt)
Packit Service 82fcde
{
Packit Service 82fcde
  const size_t optlen = strlen (opt);
Packit Service 82fcde
  char *rest = mnt->mnt_opts, *p;
Packit Service 82fcde
Packit Service 82fcde
  while ((p = strstr (rest, opt)) != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      if ((p == rest || p[-1] == ',')
Packit Service 82fcde
	  && (p[optlen] == '\0' || p[optlen] == '=' || p[optlen] == ','))
Packit Service 82fcde
	return p;
Packit Service 82fcde
Packit Service 82fcde
      rest = strchr (p, ',');
Packit Service 82fcde
      if (rest == NULL)
Packit Service 82fcde
	break;
Packit Service 82fcde
      ++rest;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return NULL;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (__hasmntopt)
Packit Service 82fcde
weak_alias (__hasmntopt, hasmntopt)