BSD 4_3_Net_2 release
[unix-history] / usr / src / usr.sbin / amd / config / mtab_file.c
index 9bec434..2344a7a 100644 (file)
@@ -1,6 +1,4 @@
 /*
 /*
- * $Id: mtab_file.c,v 5.2 90/06/23 22:20:54 jsp Rel $
- *
  * Copyright (c) 1990 Jan-Simon Pendry
  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1990 The Regents of the University of California.
  * Copyright (c) 1990 Jan-Simon Pendry
  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1990 The Regents of the University of California.
@@ -9,21 +7,38 @@
  * This code is derived from software contributed to Berkeley by
  * Jan-Simon Pendry at Imperial College, London.
  *
  * This code is derived from software contributed to Berkeley by
  * Jan-Simon Pendry at Imperial College, London.
  *
- * Redistribution and use in source and binary forms are permitted provided
- * that: (1) source distributions retain this entire copyright notice and
- * comment, and (2) distributions including binaries display the following
- * acknowledgement:  ``This product includes software developed by the
- * University of California, Berkeley and its contributors'' in the
- * documentation or other materials provided with the distribution and in
- * all advertising materials mentioning features or use of this software.
- * Neither the name of the University nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)mtab_file.c 5.3 (Berkeley) 5/12/91
+ *
+ * $Id: mtab_file.c,v 5.2.1.3 91/05/07 22:19:58 jsp Alpha $
  *
  *
- *     @(#)mtab_file.c 5.1 (Berkeley) 6/29/90
  */
 
 #include "am.h"
  */
 
 #include "am.h"
@@ -93,9 +108,144 @@ again:
 #endif /* LOCK_FCNTL */
 #endif /* MTAB_LOCKING */
 
 #endif /* LOCK_FCNTL */
 #endif /* MTAB_LOCKING */
 
+static FILE *open_locked_mtab(mtab_file, mode, fs)
+char *mtab_file;
+char *mode;
+char *fs;
+{
+       FILE *mfp = 0;
+
+#ifdef UPDATE_MTAB
+       /*
+        * There is a possible race condition if two processes enter
+        * this routine at the same time.  One will be blocked by the
+        * exclusive lock below (or by the shared lock in setmntent)
+        * and by the time the second process has the exclusive lock
+        * it will be on the wrong underlying object.  To check for this
+        * the mtab file is stat'ed before and after all the locking
+        * sequence, and if it is a different file then we assume that
+        * it may be the wrong file (only "may", since there is another
+        * race between the initial stat and the setmntent).
+        *
+        * Simpler solutions to this problem are invited...
+        */
+       int racing = 2;
+#ifdef MTAB_LOCKING
+       int rc;
+       int retries = 0;
+       struct stat st_before, st_after;
+#endif /* MTAB_LOCKING */
+
+       if (mnt_file) {
+#ifdef DEBUG
+               dlog("Forced close on %s in read_mtab", mtab_file);
+#endif /* DEBUG */
+               endmntent(mnt_file);
+               mnt_file = 0;
+       }
+
+#ifdef MTAB_LOCKING
+again:
+       if (mfp) {
+               endmntent(mfp);
+               mfp = 0;
+       }
+
+       clock_valid = 0;
+       if (stat(mtab_file, &st_before) < 0) {
+               plog(XLOG_ERROR, "%s: stat: %m", mtab_file);
+               if (errno == ESTALE) {
+                       /* happens occasionally */
+                       sleep(1);
+                       goto again;
+               }
+               return 0;
+       }
+#endif /* MTAB_LOCKING */
+#endif /* UPDATE_MTAB */
+
+eacces:
+       mfp = setmntent(mtab_file, mode);
+       if (!mfp) {
+               /*
+                * Since setmntent locks the descriptor, it
+                * is possible it can fail... so retry if
+                * needed.
+                */
+               if (errno == EACCES || errno == EAGAIN) {
+#ifdef DEBUG
+                       dlog("Blocked, trying to obtain exclusive mtab lock");
+#endif /* DEBUG */
+                       goto eacces;
+               } else if (errno == ENFILE && retries++ < NFILE_RETRIES) {
+                       sleep(1);
+                       goto eacces;
+               }
+
+               plog(XLOG_ERROR, "setmntent(\"%s\", \"%s\"): %m", mtab_file, mode);
+               return 0;
+       }
+
+#ifdef MTAB_LOCKING
+#ifdef UPDATE_MTAB
+       /*
+        * At this point we have an exclusive lock on the mount list,
+        * but it may be the wrong one so...
+        */
+
+       /*
+        * Need to get an exclusive lock on the current
+        * mount table until we have a new copy written
+        * out, when the lock is released in free_mntlist.
+        * flock is good enough since the mount table is
+        * not shared between machines.
+        */
+       do
+               rc = lock(fileno(mfp));
+       while (rc < 0 && errno == EINTR);
+       if (rc < 0) {
+               plog(XLOG_ERROR, "Couldn't lock %s: %m", mtab_file);
+               endmntent(mfp);
+               return 0;
+       }
+       /*
+        * Now check whether the mtab file has changed under our feet
+        */
+       if (stat(mtab_file, &st_after) < 0) {
+               plog(XLOG_ERROR, "%s: stat", mtab_file);
+               goto again;
+       }
+
+       if (st_before.st_dev != st_after.st_dev ||
+               st_before.st_ino != st_after.st_ino) {
+                       struct timeval tv;
+                       if (racing == 0) {
+                               /* Sometimes print a warning */
+                               plog(XLOG_WARNING,
+                                       "Possible mount table race - retrying %s", fs);
+                       }
+                       racing = (racing+1) & 3;
+                       /*
+                        * Take a nap.  From: Doug Kingston <dpk@morgan.com>
+                        */
+                       tv.tv_sec = 0;
+                       tv.tv_usec = (mypid & 0x07) << 17;
+                       if (tv.tv_usec)
+                               if (select(0, (voidp) 0, (voidp) 0, (voidp) 0, &tv) < 0)
+                                       plog(XLOG_WARNING, "mtab nap failed: %m");
+
+                       goto again;
+       }
+#endif /* UPDATE_MTAB */
+#endif /* MTAB_LOCKING */
+
+       return mfp;
+}
+
 /*
  * Unlock the mount table
  */
 /*
  * Unlock the mount table
  */
+void unlock_mntlist P((void));
 void unlock_mntlist()
 {
        /*
 void unlock_mntlist()
 {
        /*
@@ -198,7 +348,7 @@ struct mntent *mp;
        int retries = 0;
        FILE *mfp;
 enfile:
        int retries = 0;
        FILE *mfp;
 enfile:
-       mfp = setmntent(mtab, "a");
+       mfp = open_locked_mtab(mtab, "a", mp->mnt_dir);
        if (mfp) {
 #ifdef MTAB_STRIPNL
                mtab_stripnl(mp->mnt_opts);
        if (mfp) {
 #ifdef MTAB_STRIPNL
                mtab_stripnl(mp->mnt_opts);
@@ -230,6 +380,13 @@ struct mntent *mp;
        new_mp->mnt_freq = mp->mnt_freq;
        new_mp->mnt_passno = mp->mnt_passno;
 
        new_mp->mnt_freq = mp->mnt_freq;
        new_mp->mnt_passno = mp->mnt_passno;
 
+#ifdef FIXUP_MNTENT_DUP
+       /*
+        * Additional fields get dup'ed here
+        */
+       FIXUP_MNTENT_DUP(new_mp, mp);
+#endif
+
        return new_mp;
 }
 
        return new_mp;
 }
 
@@ -242,121 +399,10 @@ char *fs;
        mntlist **mpp, *mhp;
 
        struct mntent *mep;
        mntlist **mpp, *mhp;
 
        struct mntent *mep;
-       FILE *mfp = 0;
-
-#ifdef UPDATE_MTAB
-       /*
-        * There is a possible race condition if two processes enter
-        * this routine at the same time.  One will be blocked by the
-        * exclusive lock below (or by the shared lock in setmntent)
-        * and by the time the second process has the exclusive lock
-        * it will be on the wrong underlying object.  To check for this
-        * the mtab file is stat'ed before and after all the locking
-        * sequence, and if it is a different file then we assume that
-        * it may be the wrong file (only "may", since there is another
-        * race between the initial stat and the setmntent).
-        *
-        * Simpler solutions to this problem are invited...
-        */
-       int racing = 0;
-#ifdef MTAB_LOCKING
-       int rc;
-       int retries = 0;
-       struct stat st_before, st_after;
-#endif /* MTAB_LOCKING */
+       FILE *mfp = open_locked_mtab(mtab, "r+", fs);
 
 
-       if (mnt_file) {
-#ifdef DEBUG
-               dlog("Forced close on %s in read_mtab", mtab);
-#endif /* DEBUG */
-               endmntent(mnt_file);
-               mnt_file = 0;
-       }
-
-#ifdef MTAB_LOCKING
-again:
-       if (mfp) {
-               endmntent(mfp);
-               mfp = 0;
-       }
-
-       clock_valid = 0;
-       if (stat(mtab, &st_before) < 0) {
-               plog(XLOG_ERROR, "%s: stat: %m", mtab);
-               if (errno == ESTALE) {
-                       /* happens occasionally */
-                       sleep(1);
-                       goto again;
-               }
+       if (!mfp)
                return 0;
                return 0;
-       }
-#endif /* MTAB_LOCKING */
-#endif /* UPDATE_MTAB */
-
-eacces:
-       mfp = setmntent(mtab, "r+");
-       if (!mfp) {
-               /*
-                * Since setmntent locks the descriptor, it
-                * is possible it can fail... so retry if
-                * needed.
-                */
-               if (errno == EACCES || errno == EAGAIN) {
-#ifdef DEBUG
-                       dlog("Blocked, trying to obtain exclusive mtab lock");
-#endif /* DEBUG */
-                       goto eacces;
-               } else if (errno == ENFILE && retries++ < NFILE_RETRIES) {
-                       sleep(1);
-                       goto eacces;
-               }
-
-               plog(XLOG_ERROR, "setmntent(\"%s\", \"r+\"): %m", mtab);
-               return 0;
-       }
-
-#ifdef MTAB_LOCKING
-#ifdef UPDATE_MTAB
-       /*
-        * At this point we have an exclusive lock on the mount list,
-        * but it may be the wrong one so...
-        */
-
-       /*
-        * Need to get an exclusive lock on the current
-        * mount table until we have a new copy written
-        * out, when the lock is released in free_mntlist.
-        * flock is good enough since the mount table is
-        * not shared between machines.
-        */
-       do
-               rc = lock(fileno(mfp));
-       while (rc < 0 && errno == EINTR);
-       if (rc < 0) {
-               plog(XLOG_ERROR, "Couldn't lock %s: %m", mtab);
-               endmntent(mfp);
-               return 0;
-       }
-       /*
-        * Now check whether the mtab file has changed under our feet
-        */
-       if (stat(mtab, &st_after) < 0) {
-               plog(XLOG_ERROR, "%s: stat", mtab);
-               goto again;
-       }
-
-       if (st_before.st_dev != st_after.st_dev ||
-               st_before.st_ino != st_after.st_ino) {
-                       if (racing == 0) {
-                               /* Sometimes print a warning */
-                               plog(XLOG_WARNING,
-                                       "Possible mount table race - retrying %s", fs);
-                       }
-                       racing = (racing+1) & 3;
-                       goto again;
-       }
-#endif /* UPDATE_MTAB */
-#endif /* MTAB_LOCKING */
 
        mpp = &mhp;
 
 
        mpp = &mhp;