summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShehjar Tikoo <shehjart@gluster.com>2009-05-20 22:50:10 +0000
committerAnand V. Avati <avati@dev.gluster.com>2009-05-20 22:47:17 -0700
commitef7fcc0d7c2695ab3b10477b3e1290e43831da99 (patch)
treee5f7d4e4ed0e2255e14c02a1b78fa123655ea08f
parent5bb6653c434c74b5f2d5b706f60f8d4149a40a2d (diff)
booster: Move fstab parsing into booster from libglusterfs
This is another attempt at fixing build problems on Solaris. I am told that booster build is disabled on Solaris and I know that it is disabled on Mac OS X also. Getting it to work on both these systems is now on my TODO list, mainly because on both these systems, we can have a glusterfs client running without requiring FUSE. Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
-rw-r--r--booster/src/Makefile.am2
-rw-r--r--booster/src/booster.c109
-rw-r--r--booster/src/booster_fstab.c415
-rw-r--r--booster/src/booster_fstab.h (renamed from libglusterfs/src/glusterfs_fstab.h)33
-rw-r--r--libglusterfs/src/Makefile.am4
-rw-r--r--libglusterfs/src/glusterfs_fstab.c309
6 files changed, 436 insertions, 436 deletions
diff --git a/booster/src/Makefile.am b/booster/src/Makefile.am
index 1b3be737ee5..50aaa668103 100644
--- a/booster/src/Makefile.am
+++ b/booster/src/Makefile.am
@@ -2,7 +2,7 @@ xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/performance
ldpreload_PROGRAMS = glusterfs-booster.so
ldpreloaddir = $(libdir)/glusterfs/
-glusterfs_booster_so_SOURCES = booster.c booster_stat.c
+glusterfs_booster_so_SOURCES = booster.c booster_stat.c booster_fstab.c
glusterfs_booster_so_CFLAGS = -I$(top_srcdir)/libglusterfsclient/src/ -D_GNU_SOURCE -D$(GF_HOST_OS) -fPIC -Wall \
-pthread $(GF_BOOSTER_CFLAGS)
glusterfs_booster_so_CPPFLAGS = -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE \
diff --git a/booster/src/booster.c b/booster/src/booster.c
index aeb4caa42f6..264d6772b47 100644
--- a/booster/src/booster.c
+++ b/booster/src/booster.c
@@ -42,7 +42,6 @@
#include <dirent.h>
#include <sys/statfs.h>
#include <sys/statvfs.h>
-#include <glusterfs_fstab.h>
#ifndef GF_UNIT_KB
#define GF_UNIT_KB 1024
@@ -224,6 +223,7 @@ typedef struct booster_mount_table booster_mount_table_t;
static fdtable_t *booster_glfs_fdtable = NULL;
static booster_mount_table_t *booster_mount_table = NULL;
+extern int booster_configure (char *confpath);
/* This is dup'ed every time VMP open/creat wants a new fd.
* This is needed so we occupy an entry in the process' file
* table.
@@ -239,113 +239,6 @@ booster_get_process_fd ()
#define DEFAULT_BOOSTER_CONF CONFDIR"/booster.conf"
#define BOOSTER_CONF_ENV_VAR "GLUSTERFS_BOOSTER_FSTAB"
-void
-clean_init_params (glusterfs_init_params_t *ipars)
-{
- if (!ipars)
- return;
-
- if (ipars->volume_name)
- free (ipars->volume_name);
-
- if (ipars->specfile)
- free (ipars->specfile);
-
- if (ipars->logfile)
- free (ipars->logfile);
-
- if (ipars->loglevel)
- free (ipars->loglevel);
-
- return;
-}
-
-char *
-get_option_value (char *opt)
-{
- char *val = NULL;
- char *saveptr = NULL;
- char *copy_opt = NULL;
- char *retval = NULL;
-
- copy_opt = strdup (opt);
-
- /* Get the = before the value of the option. */
- val = index (copy_opt, '=');
- if (val) {
- /* Move to start of option */
- ++val;
-
- /* Now, to create a '\0' delimited string out of the
- * options string, first get the position where the
- * next option starts, that would be the next ','.
- */
- saveptr = index (val, ',');
- if (saveptr)
- *saveptr = '\0';
- retval = strdup (val);
- }
-
- free (copy_opt);
-
- return retval;
-}
-
-void
-booster_mount (struct glusterfs_mntent *ent)
-{
- char *opt = NULL;
- glusterfs_init_params_t ipars;
-
- if (!ent)
- return;
-
- if ((strcmp (ent->mnt_type, "glusterfs") != 0))
- return;
-
- memset (&ipars, 0, sizeof (glusterfs_init_params_t));
- if (ent->mnt_fsname)
- ipars.specfile = strdup (ent->mnt_fsname);
-
- opt = glusterfs_fstab_hasoption (ent, "subvolume");
- if (opt)
- ipars.volume_name = get_option_value (opt);
-
- opt = glusterfs_fstab_hasoption (ent, "logfile");
- if (opt)
- ipars.logfile = get_option_value (opt);
-
- opt = glusterfs_fstab_hasoption (ent, "loglevel");
- if (opt)
- ipars.loglevel = get_option_value (opt);
-
- glusterfs_mount (ent->mnt_dir, &ipars);
- clean_init_params (&ipars);
-}
-
-int
-booster_configure (char *confpath)
-{
- int ret = -1;
- glusterfs_fstab_t *handle = NULL;
- struct glusterfs_mntent *ent = NULL;
-
- if (!confpath)
- goto out;
-
- handle = glusterfs_fstab_init (confpath, "r");
- if (!handle)
- goto out;
-
- while ((ent = glusterfs_fstab_getent (handle)) != NULL)
- booster_mount (ent);
-
- glusterfs_fstab_close (handle);
- ret = 0;
-out:
- return ret;
-}
-
static int32_t
booster_put_handle (booster_mount_table_t *table,
dev_t st_dev,
diff --git a/booster/src/booster_fstab.c b/booster/src/booster_fstab.c
new file mode 100644
index 00000000000..dba785b5b4b
--- /dev/null
+++ b/booster/src/booster_fstab.c
@@ -0,0 +1,415 @@
+/* Utilities for reading/writing fstab, mtab, etc.
+ Copyright (C) 1995-2000, 2001, 2002, 2003, 2006
+ 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <alloca.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "booster_fstab.h"
+#include <stdlib.h>
+#include <libglusterfsclient.h>
+
+/* Prepare to begin reading and/or writing mount table entries from the
+ beginning of FILE. MODE is as for `fopen'. */
+glusterfs_fstab_t *
+glusterfs_fstab_init (const char *file, const char *mode)
+{
+ glusterfs_fstab_t *handle = NULL;
+ handle = calloc (1, sizeof (glusterfs_fstab_t));
+ if (!handle)
+ goto out;
+
+ FILE *result = fopen (file,mode);
+ if (result != NULL) {
+ handle->fp = result;
+ } else {
+ free (handle);
+ handle = NULL;
+ }
+
+out:
+
+ return handle;
+}
+
+int
+glusterfs_fstab_close (glusterfs_fstab_t *h)
+{
+ if (!h)
+ return -1;
+
+ if (h->fp)
+ fclose (h->fp);
+
+ return 0;
+}
+
+/* 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 glusterfs_mntent *
+__glusterfs_fstab_getent (FILE *stream, struct glusterfs_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 glusterfs_mntent *
+glusterfs_fstab_getent (glusterfs_fstab_t *h)
+{
+ if (!h)
+ return NULL;
+
+ if (!h->fp)
+ return NULL;
+
+ return __glusterfs_fstab_getent (h->fp, &h->tmpent, h->buf,
+ GF_MNTENT_BUFSIZE);
+}
+
+/* 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; \
+ else \
+ ++rp; \
+ \
+ if (*rp != '\0') \
+ { \
+ /* In the worst case the length of the string \
+ * can increase to four times the current \
+ * length. */ \
+ char *wp; \
+ \
+ rp = name; \
+ name = wp = (char *) alloca (strlen (name) * 4 + 1); \
+ \
+ do { \
+ if (*rp == ' ') \
+ { \
+ *wp++ = '\\'; \
+ *wp++ = '0'; \
+ *wp++ = '4'; \
+ *wp++ = '0'; \
+ } \
+ else if (*rp == '\t') \
+ { \
+ *wp++ = '\\'; \
+ *wp++ = '0'; \
+ *wp++ = '1'; \
+ *wp++ = '1'; \
+ } \
+ else if (*rp == '\n') \
+ { \
+ *wp++ = '\\'; \
+ *wp++ = '0'; \
+ *wp++ = '1'; \
+ *wp++ = '2'; \
+ } \
+ else if (*rp == '\\') \
+ { \
+ *wp++ = '\\'; \
+ *wp++ = '\\'; \
+ } \
+ else \
+ *wp++ = *rp; \
+ } while (*rp++ != '\0'); \
+ } \
+ } while (0) \
+
+
+int
+glusterfs_fstab_addent (glusterfs_fstab_t *h,
+ const struct glusterfs_mntent *mnt)
+{
+ struct glusterfs_mntent mntcopy = *mnt;
+ if (!h)
+ return -1;
+
+ if (!h->fp)
+ return -1;
+
+ if (fseek (h->fp, 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 (h->fp, "%s %s %s %s %d %d\n",
+ mntcopy.mnt_fsname,
+ mntcopy.mnt_dir,
+ mntcopy.mnt_type,
+ mntcopy.mnt_opts,
+ mntcopy.mnt_freq,
+ mntcopy.mnt_passno)
+ < 0 ? 1 : 0);
+}
+
+
+/* Search MNT->mnt_opts for an option matching OPT.
+ Returns the address of the substring, or null if none found. */
+char *
+glusterfs_fstab_hasoption (const struct glusterfs_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;
+}
+
+void
+clean_init_params (glusterfs_init_params_t *ipars)
+{
+ if (!ipars)
+ return;
+
+ if (ipars->volume_name)
+ free (ipars->volume_name);
+
+ if (ipars->specfile)
+ free (ipars->specfile);
+
+ if (ipars->logfile)
+ free (ipars->logfile);
+
+ if (ipars->loglevel)
+ free (ipars->loglevel);
+
+ return;
+}
+
+char *
+get_option_value (char *opt)
+{
+ char *val = NULL;
+ char *saveptr = NULL;
+ char *copy_opt = NULL;
+ char *retval = NULL;
+
+ copy_opt = strdup (opt);
+
+ /* Get the = before the value of the option. */
+ val = index (copy_opt, '=');
+ if (val) {
+ /* Move to start of option */
+ ++val;
+
+ /* Now, to create a '\0' delimited string out of the
+ * options string, first get the position where the
+ * next option starts, that would be the next ','.
+ */
+ saveptr = index (val, ',');
+ if (saveptr)
+ *saveptr = '\0';
+ retval = strdup (val);
+ }
+
+ free (copy_opt);
+
+ return retval;
+}
+
+void
+booster_mount (struct glusterfs_mntent *ent)
+{
+ char *opt = NULL;
+ glusterfs_init_params_t ipars;
+
+ if (!ent)
+ return;
+
+ if ((strcmp (ent->mnt_type, "glusterfs") != 0))
+ return;
+
+ memset (&ipars, 0, sizeof (glusterfs_init_params_t));
+ if (ent->mnt_fsname)
+ ipars.specfile = strdup (ent->mnt_fsname);
+
+ opt = glusterfs_fstab_hasoption (ent, "subvolume");
+ if (opt)
+ ipars.volume_name = get_option_value (opt);
+
+ opt = glusterfs_fstab_hasoption (ent, "logfile");
+ if (opt)
+ ipars.logfile = get_option_value (opt);
+
+ opt = glusterfs_fstab_hasoption (ent, "loglevel");
+ if (opt)
+ ipars.loglevel = get_option_value (opt);
+
+ glusterfs_mount (ent->mnt_dir, &ipars);
+ clean_init_params (&ipars);
+}
+
+int
+booster_configure (char *confpath)
+{
+ int ret = -1;
+ glusterfs_fstab_t *handle = NULL;
+ struct glusterfs_mntent *ent = NULL;
+
+ if (!confpath)
+ goto out;
+
+ handle = glusterfs_fstab_init (confpath, "r");
+ if (!handle)
+ goto out;
+
+ while ((ent = glusterfs_fstab_getent (handle)) != NULL)
+ booster_mount (ent);
+
+ glusterfs_fstab_close (handle);
+ ret = 0;
+out:
+ return ret;
+}
+
+
diff --git a/libglusterfs/src/glusterfs_fstab.h b/booster/src/booster_fstab.h
index 5d6c6a77f81..9bab04c5aa0 100644
--- a/libglusterfs/src/glusterfs_fstab.h
+++ b/booster/src/booster_fstab.h
@@ -19,11 +19,12 @@
#ifndef GLUSTERFS_FSTAB_MNTENT_H
#define GLUSTERFS_FSTAB_MNTENT_H 1
-
-#include <features.h>
-#include <stdio.h>
-#include <paths.h>
-
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "compat.h"
/* General filesystem types. */
#define GF_MNTTYPE_IGNORE "ignore" /* Ignore this entry. */
@@ -42,14 +43,14 @@
/* Structure describing a mount table entry. */
struct glusterfs_mntent
- {
- char *mnt_fsname; /* Device or server for filesystem. */
- char *mnt_dir; /* Directory mounted on. */
- char *mnt_type; /* Type of filesystem: ufs, nfs, etc. */
- char *mnt_opts; /* Comma-separated options for fs. */
- int mnt_freq; /* Dump frequency (in days). */
- int mnt_passno; /* Pass number for `fsck'. */
- };
+{
+ char *mnt_fsname; /* Device or server for filesystem. */
+ char *mnt_dir; /* Directory mounted on. */
+ char *mnt_type; /* Type of filesystem: ufs, nfs, etc. */
+ char *mnt_opts; /* Comma-separated options for fs. */
+ int mnt_freq; /* Dump frequency (in days). */
+ int mnt_passno; /* Pass number for `fsck'. */
+};
#define GF_MNTENT_BUFSIZE 1024
typedef struct glusterfs_fstab_handle {
@@ -62,14 +63,14 @@ typedef struct glusterfs_fstab_handle {
/* Prepare to begin reading and/or writing mount table entries from the
beginning of FILE. MODE is as for `fopen'. */
extern glusterfs_fstab_t *glusterfs_fstab_init (const char *file,
- const char *mode);
+ const char *mode);
extern struct glusterfs_mntent *glusterfs_fstab_getent (glusterfs_fstab_t *h);
/* Write the mount table entry described by MNT to STREAM.
Return zero on success, nonzero on failure. */
extern int glusterfs_fstab_addent (glusterfs_fstab_t *h,
- const struct glusterfs_mntent *mnt);
+ const struct glusterfs_mntent *mnt);
/* Close a stream opened with `glusterfs_fstab_init'. */
extern int glusterfs_fstab_close (glusterfs_fstab_t *h);
@@ -77,6 +78,6 @@ extern int glusterfs_fstab_close (glusterfs_fstab_t *h);
/* Search MNT->mnt_opts for an option matching OPT.
Returns the address of the substring, or null if none found. */
extern char *glusterfs_fstab_hasoption (const struct glusterfs_mntent *mnt,
- const char *opt);
+ const char *opt);
#endif
diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am
index 2863c755c18..8ff35fbb27a 100644
--- a/libglusterfs/src/Makefile.am
+++ b/libglusterfs/src/Makefile.am
@@ -6,9 +6,9 @@ libglusterfs_la_LIBADD = @LEXLIB@
lib_LTLIBRARIES = libglusterfs.la
-libglusterfs_la_SOURCES = dict.c spec.lex.c y.tab.c xlator.c logging.c hashfn.c defaults.c scheduler.c common-utils.c transport.c timer.c inode.c call-stub.c compat.c authenticate.c fd.c compat-errno.c event.c mem-pool.c gf-dirent.c syscall.c iobuf.c glusterfs_fstab.c
+libglusterfs_la_SOURCES = dict.c spec.lex.c y.tab.c xlator.c logging.c hashfn.c defaults.c scheduler.c common-utils.c transport.c timer.c inode.c call-stub.c compat.c authenticate.c fd.c compat-errno.c event.c mem-pool.c gf-dirent.c syscall.c iobuf.c
-noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h logging.h protocol.h scheduler.h xlator.h transport.h stack.h timer.h list.h inode.h call-stub.h compat.h authenticate.h fd.h revision.h compat-errno.h event.h mem-pool.h byte-order.h gf-dirent.h locking.h syscall.h iobuf.h glusterfs_fstab.h
+noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h logging.h protocol.h scheduler.h xlator.h transport.h stack.h timer.h list.h inode.h call-stub.h compat.h authenticate.h fd.h revision.h compat-errno.h event.h mem-pool.h byte-order.h gf-dirent.h locking.h syscall.h iobuf.h
EXTRA_DIST = spec.l spec.y
diff --git a/libglusterfs/src/glusterfs_fstab.c b/libglusterfs/src/glusterfs_fstab.c
deleted file mode 100644
index b21197b1d91..00000000000
--- a/libglusterfs/src/glusterfs_fstab.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/* Utilities for reading/writing fstab, mtab, etc.
- Copyright (C) 1995-2000, 2001, 2002, 2003, 2006
- 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
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#include <alloca.h>
-#include <stdio.h>
-#include <stdio_ext.h>
-#include <string.h>
-#include <sys/types.h>
-#include "glusterfs_fstab.h"
-#include <stdlib.h>
-
-/* Prepare to begin reading and/or writing mount table entries from the
- beginning of FILE. MODE is as for `fopen'. */
-glusterfs_fstab_t *
-glusterfs_fstab_init (const char *file, const char *mode)
-{
- glusterfs_fstab_t *handle = NULL;
- /* Extend the mode parameter with "c" to disable cancellation in the
- I/O functions. */
- size_t modelen = strlen (mode);
- char newmode[modelen + 2];
- memcpy (mempcpy (newmode, mode, modelen), "c", 2);
-
- handle = calloc (1, sizeof (glusterfs_fstab_t));
- if (!handle)
- goto out;
-
- FILE *result = fopen (file, newmode);
- if (result != NULL) {
- /* We do the locking ourselves. */
- __fsetlocking (result, FSETLOCKING_BYCALLER);
- handle->fp = result;
- } else {
- free (handle);
- handle = NULL;
- }
-
-out:
-
- return handle;
-}
-
-int
-glusterfs_fstab_close (glusterfs_fstab_t *h)
-{
- if (!h)
- return -1;
-
- if (h->fp)
- fclose (h->fp);
-
- return 0;
-}
-
-/* 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 glusterfs_mntent *
-__glusterfs_fstab_getent (FILE *stream, struct glusterfs_mntent *mp,
- char *buffer, int bufsiz)
-{
- char *cp;
- char *head;
-
- flockfile (stream);
- do
- {
- char *end_ptr;
-
- if (fgets_unlocked (buffer, bufsiz, stream) == NULL)
- {
- funlockfile (stream);
- 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_unlocked (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;
- }
- funlockfile (stream);
-
- return mp;
-}
-
-struct glusterfs_mntent *
-glusterfs_fstab_getent (glusterfs_fstab_t *h)
-{
- if (!h)
- return NULL;
-
- if (!h->fp)
- return NULL;
-
- return __glusterfs_fstab_getent (h->fp, &h->tmpent, h->buf,
- GF_MNTENT_BUFSIZE);
-}
-
-/* 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; \
- else \
- ++rp; \
- \
- if (*rp != '\0') \
- { \
- /* In the worst case the length of the string can increase to \
- founr times the current length. */ \
- char *wp; \
- \
- rp = name; \
- name = wp = (char *) alloca (strlen (name) * 4 + 1); \
- \
- do \
- if (*rp == ' ') \
- { \
- *wp++ = '\\'; \
- *wp++ = '0'; \
- *wp++ = '4'; \
- *wp++ = '0'; \
- } \
- else if (*rp == '\t') \
- { \
- *wp++ = '\\'; \
- *wp++ = '0'; \
- *wp++ = '1'; \
- *wp++ = '1'; \
- } \
- else if (*rp == '\n') \
- { \
- *wp++ = '\\'; \
- *wp++ = '0'; \
- *wp++ = '1'; \
- *wp++ = '2'; \
- } \
- else if (*rp == '\\') \
- { \
- *wp++ = '\\'; \
- *wp++ = '\\'; \
- } \
- else \
- *wp++ = *rp; \
- while (*rp++ != '\0'); \
- } \
- } while (0)
-
-
-int
-glusterfs_fstab_addent (glusterfs_fstab_t *h,
- const struct glusterfs_mntent *mnt)
-{
- struct glusterfs_mntent mntcopy = *mnt;
- if (!h)
- return -1;
-
- if (!h->fp)
- return -1;
-
- if (fseek (h->fp, 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 (h->fp, "%s %s %s %s %d %d\n",
- mntcopy.mnt_fsname,
- mntcopy.mnt_dir,
- mntcopy.mnt_type,
- mntcopy.mnt_opts,
- mntcopy.mnt_freq,
- mntcopy.mnt_passno)
- < 0 ? 1 : 0);
-}
-
-
-/* Search MNT->mnt_opts for an option matching OPT.
- Returns the address of the substring, or null if none found. */
-char *
-glusterfs_fstab_hasoption (const struct glusterfs_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;
-}