[lxc-devel] [PATCH 18/24] Add local implementation of mntent.h
Serge Hallyn
serge.hallyn at canonical.com
Tue Jan 8 18:33:16 UTC 2013
Quoting Stéphane Graber (stgraber at ubuntu.com):
> Bionic (at least) is missing some of the usual mntent functions.
> This adds code defining those that we need when they're missing from the C
> library.
>
> Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>
I could see someone in the future deciding that ../include should be
added to -I, which would cause our include/mntent.h to always be
included in favor of the system one (iiuc). Not sure whether that's
worth worrying about. If so, perhaps rename to lxcmntent.h?
> ---
> configure.ac | 2 +-
> src/include/mntent.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++
> src/include/mntent.h | 32 ++++++++++
> src/lxc/Makefile.am | 6 +-
> src/lxc/cgroup.c | 7 ++-
> src/lxc/conf.c | 7 ++-
> 6 files changed, 222 insertions(+), 5 deletions(-)
> create mode 100644 src/include/mntent.c
> create mode 100644 src/include/mntent.h
>
> diff --git a/configure.ac b/configure.ac
> index 0d50bec..3770e8b 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -227,7 +227,7 @@ AC_CHECK_HEADERS([sys/signalfd.h pty.h sys/capability.h sys/personality.h utmpx.
> AC_CHECK_FUNCS([setns pivot_root sethostname unshare])
>
> # Check for some functions
> -AC_CHECK_FUNCS([getline fgetln openpty])
> +AC_CHECK_FUNCS([getline fgetln openpty hasmntopt setmntent endmntent])
>
> # Check for some standard binaries
> AC_PROG_GCC_TRADITIONAL
> diff --git a/src/include/mntent.c b/src/include/mntent.c
> new file mode 100644
> index 0000000..a96cd81
> --- /dev/null
> +++ b/src/include/mntent.c
> @@ -0,0 +1,173 @@
> +#include <mntent.h>
> +#include <stdio.h>
> +#include <string.h>
> +
> +/* 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] == '1')
> + {
> + /* \011 is a TAB. */
> + *wp++ = '\t';
> + rp += 3;
> + }
> + else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '2')
> + {
> + /* \012 is a NEWLINE. */
> + *wp++ = '\n';
> + rp += 3;
> + }
> + else if (rp[0] == '\\' && rp[1] == '\\')
> + {
> + /* We have to escape \\ to be able to represent all characters. */
> + *wp++ = '\\';
> + rp += 1;
> + }
> + else if (rp[0] == '\\' && rp[1] == '1' && rp[2] == '3' && rp[3] == '4')
> + {
> + /* \134 is also \\. */
> + *wp++ = '\\';
> + rp += 3;
> + }
> + 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;
> +
> + do
> + {
> + char *end_ptr;
> +
> + if (fgets (buffer, bufsiz, stream) == NULL)
> + {
> + return NULL;
> + }
> +
> + end_ptr = strchr (buffer, '\n');
> + if (end_ptr != NULL) /* chop newline */
> + *end_ptr = '\0';
> + else
> + {
> + /* Not the whole line was read. Do it now but forget it. */
> + char tmp[1024];
> + while (fgets (tmp, sizeof tmp, stream) != NULL)
> + if (strchr (tmp, '\n') != NULL)
> + break;
> + }
> +
> + head = buffer + strspn (buffer, " \t");
> + /* skip empty lines and comment lines: */
> + }
> + while (head[0] == '\0' || head[0] == '#');
> +
> + cp = strsep (&head, " \t");
> + mp->mnt_fsname = cp != NULL ? decode_name (cp) : (char *) "";
> + if (head)
> + head += strspn (head, " \t");
> + cp = strsep (&head, " \t");
> + mp->mnt_dir = cp != NULL ? decode_name (cp) : (char *) "";
> + if (head)
> + head += strspn (head, " \t");
> + cp = strsep (&head, " \t");
> + mp->mnt_type = cp != NULL ? decode_name (cp) : (char *) "";
> + if (head)
> + head += strspn (head, " \t");
> + 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:
> + mp->mnt_freq = 0;
> + case 1:
> + mp->mnt_passno = 0;
> + case 2:
> + break;
> + }
> +
> + return mp;
> +}
> +
> +struct mntent *getmntent (FILE *stream)
> +{
> + static struct mntent m;
> + static char *getmntent_buffer;
> +
> + #define BUFFER_SIZE 4096
> + if (getmntent_buffer == NULL) {
> + getmntent_buffer = (char *) malloc (BUFFER_SIZE);
> + }
> +
> + return getmntent_r (stream, &m, getmntent_buffer, BUFFER_SIZE);
> + #undef BUFFER_SIZE
> +}
> +
> +
> +/* Prepare to begin reading and/or writing mount table entries from the
> + beginning of FILE. MODE is as for `fopen'. */
> +FILE *setmntent (const char *file, const char *mode)
> +{
> + /* Extend the mode parameter with "c" to disable cancellation in the
> + I/O functions and "e" to set FD_CLOEXEC. */
> + size_t modelen = strlen (mode);
> + char newmode[modelen + 3];
> + memcpy (newmode, mode, modelen);
> + memcpy (newmode + modelen, "ce", 3);
> + FILE *result = fopen (file, newmode);
> +
> + return result;
> +}
> +
> +
> +/* Close a stream opened with `setmntent'. */
> +int endmntent (FILE *stream)
> +{
> + if (stream) /* SunOS 4.x allows for NULL stream */
> + fclose (stream);
> + return 1; /* SunOS 4.x says to always return 1 */
> +}
> +
> +/* Search MNT->mnt_opts for an option matching OPT.
> + Returns the address of the substring, or null if none found. */
> +char *hasmntopt (const struct mntent *mnt, const char *opt)
> +{
> + const size_t optlen = strlen (opt);
> + char *rest = mnt->mnt_opts, *p;
> +
> + while ((p = strstr (rest, opt)) != NULL)
> + {
> + if ((p == rest || p[-1] == ',')
> + && (p[optlen] == '\0' || p[optlen] == '=' || p[optlen] == ','))
> + return p;
> +
> + rest = strchr (p, ',');
> + if (rest == NULL)
> + break;
> + ++rest;
> + }
> +
> + return NULL;
> +}
> diff --git a/src/include/mntent.h b/src/include/mntent.h
> new file mode 100644
> index 0000000..3f1d16f
> --- /dev/null
> +++ b/src/include/mntent.h
> @@ -0,0 +1,32 @@
> +#ifndef _mntent_h
> +#define _mntent_h
> +
> +#include <../config.h>
> +
> +#if IS_BIONIC
> +struct mntent
> +{
> + char* mnt_fsname;
> + char* mnt_dir;
> + char* mnt_type;
> + char* mnt_opts;
> + int mnt_freq;
> + int mnt_passno;
> +};
> +
> +extern struct mntent *getmntent (FILE *stream);
> +#endif
> +
> +#ifndef HAVE_SETMNTENT
> +FILE *setmntent (const char *file, const char *mode);
> +#endif
> +
> +#ifndef HAVE_ENDMNTENT
> +int endmntent (FILE *stream);
> +#endif
> +
> +#ifndef HAVE_HASMNTOPT
> +extern char *hasmntopt (const struct mntent *mnt, const char *opt);
> +#endif
> +
> +#endif
> diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
> index 3d800d5..8bc7b4b 100644
> --- a/src/lxc/Makefile.am
> +++ b/src/lxc/Makefile.am
> @@ -20,7 +20,8 @@ pkginclude_HEADERS = \
> if IS_BIONIC
> pkginclude_HEADERS += \
> ../include/getline.h \
> - ../include/openpty.h
> + ../include/openpty.h \
> + ../include/mntent.h
> endif
>
> sodir=$(libdir)
> @@ -70,7 +71,8 @@ liblxc_so_SOURCES = \
> if IS_BIONIC
> liblxc_so_SOURCES += \
> ../include/getline.c ../include/getline.h \
> - ../include/openpty.c ../include/openpty.h
> + ../include/openpty.c ../include/openpty.h \
> + ../include/mntent.c ../include/mntent.h
> endif
>
> AM_CFLAGS=-I$(top_srcdir)/src \
> diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
> index f6243b8..0f2057f 100644
> --- a/src/lxc/cgroup.c
> +++ b/src/lxc/cgroup.c
> @@ -25,7 +25,6 @@
> #undef _GNU_SOURCE
> #include <stdlib.h>
> #include <errno.h>
> -#include <mntent.h>
> #include <unistd.h>
> #include <string.h>
> #include <dirent.h>
> @@ -44,6 +43,12 @@
> #include <lxc/cgroup.h>
> #include <lxc/start.h>
>
> +#if IS_BIONIC
> +#include <../include/mntent.h>
> +#else
> +#include <mntent.h>
> +#endif
> +
> lxc_log_define(lxc_cgroup, lxc);
>
> #define MTAB "/proc/mounts"
> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index 4a2fd22..e6efcf0 100644
> --- a/src/lxc/conf.c
> +++ b/src/lxc/conf.c
> @@ -28,7 +28,6 @@
> #include <errno.h>
> #include <string.h>
> #include <dirent.h>
> -#include <mntent.h>
> #include <unistd.h>
> #include <sys/wait.h>
> #include <sys/syscall.h>
> @@ -78,6 +77,12 @@
> #include <sys/personality.h>
> #endif
>
> +#if IS_BIONIC
> +#include <../include/mntent.h>
> +#else
> +#include <mntent.h>
> +#endif
> +
> #include "lxcseccomp.h"
>
> lxc_log_define(lxc_conf, lxc);
> --
> 1.8.0
>
>
> ------------------------------------------------------------------------------
> Master SQL Server Development, Administration, T-SQL, SSAS, SSIS, SSRS
> and more. Get SQL Server skills now (including 2012) with LearnDevNow -
> 200+ hours of step-by-step video tutorials by Microsoft MVPs and experts.
> SALE $99.99 this month only - learn more at:
> http://p.sf.net/sfu/learnmore_122512
> _______________________________________________
> Lxc-devel mailing list
> Lxc-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel
More information about the lxc-devel
mailing list