1/* $NetBSD$ */ 2 3/* 4 * Copyright (c) 1997-2009 Erez Zadok 5 * Copyright (c) 1990 Jan-Simon Pendry 6 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 7 * Copyright (c) 1990 The Regents of the University of California. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * Jan-Simon Pendry at Imperial College, London. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgment: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * 42 * File: am-utils/conf/mtab/mtab_svr4.c 43 * 44 * How to manage the mount table file. Based on other SVR3 ports. 45 * -Erez Zadok <ezk@cs.columbia.edu> 46 */ 47 48#ifdef HAVE_CONFIG_H 49# include <config.h> 50#endif /* HAVE_CONFIG_H */ 51#include <am_defs.h> 52#include <amu.h> 53 54/* 55 * file descriptor for lock file 56 * values: -1 no file-descriptor was set yet (or mnttab unlocked, or error 57 * in locking). 58 * >=0 legal file-descriptor value (file lock succeeded) 59 */ 60static int mntent_lock_fd = -1; 61 62 63#ifdef MOUNT_TABLE_ON_FILE 64static char mtlckname[] = "/etc/.mnttab.lock"; 65#endif /* MOUNT_TABLE_ON_FILE */ 66 67 68/****************************************************************************/ 69/*** Private functions */ 70/****************************************************************************/ 71 72static void 73unlockmnttab(void) 74{ 75#ifdef MOUNT_TABLE_ON_FILE 76 if (mntent_lock_fd >= 0) { 77 close(mntent_lock_fd); 78 mntent_lock_fd = -1; 79 } 80#endif /* MOUNT_TABLE_ON_FILE */ 81} 82 83 84#ifdef MOUNT_TABLE_ON_FILE 85static int 86lockfile(int fd, int type) 87{ 88 struct flock lk; 89 int ret; 90 91 lk.l_type = type; 92 lk.l_whence = 0; 93 lk.l_start = 0; 94 lk.l_len = 0; 95 96 /* 97 * F_SETLKW means to block until the read or write block is free to be 98 * locked. 99 */ 100 ret = fcntl(fd, F_SETLKW, &lk); 101 return ret; 102} 103#endif /* MOUNT_TABLE_ON_FILE */ 104 105 106/* return 0 if locking succeeded, -1 if failed */ 107static int 108lockmnttab(void) 109{ 110#ifdef MOUNT_TABLE_ON_FILE 111 /* if mnttab file is locked, all is well */ 112 if (mntent_lock_fd >= 0) 113 return 0; 114 115 /* need to lock mnttab file. first, open the file */ 116 mntent_lock_fd = open(mtlckname, O_RDWR | O_CREAT, 0600); 117 if (mntent_lock_fd < 0) { 118 plog(XLOG_ERROR, "Unable to open/creat %s: %m", mtlckname); 119 return -1; 120 } 121 122 /* if succeeded in opening the file, try to lock it */ 123 if (lockfile(mntent_lock_fd, F_WRLCK) < 0) { 124 close(mntent_lock_fd); 125 mntent_lock_fd = -1; 126#ifdef DEBUG 127 dlog("lock %s failed: %m", mtlckname); 128#endif /* DEBUG */ 129 return -1; 130 } 131#else /* not MOUNT_TABLE_ON_FILE */ 132 /* fake lock for in-kernel mount table */ 133#endif /* not MOUNT_TABLE_ON_FILE */ 134 135 /* finally, succeeded in also locking the file */ 136 return 0; 137} 138 139 140/* 141 * Convert from solaris mnttab to Amd mntent. Since am-utils uses 142 * native "struct mnttab" if available, this really copies fields of 143 * the same structure. 144 */ 145static mntent_t * 146mnt_dup(const mntent_t *mtp) 147{ 148 mntent_t *mep = ALLOC(mntent_t); 149 150 mep->mnt_fsname = strdup(mtp->mnt_fsname); 151 mep->mnt_dir = strdup(mtp->mnt_dir); 152 mep->mnt_type = strdup(mtp->mnt_type); 153 mep->mnt_opts = strdup(mtp->mnt_opts); 154 mep->mnt_time = strdup(mtp->mnt_time); 155 156 return mep; 157} 158 159 160/* 161 * Adjust arguments in mntent_t. 162 */ 163#ifdef MOUNT_TABLE_ON_FILE 164static mntent_t * 165update_mnttab_fields(const mntent_t *mnt) 166{ 167 static mntent_t mt; 168 static char timestr[16]; 169 struct timeval tv; 170 171 /* most fields don't change, only update mnt_time below */ 172 mt.mnt_fsname = mnt->mnt_fsname; 173 mt.mnt_dir = mnt->mnt_dir; 174 mt.mnt_type = mnt->mnt_type; 175 mt.mnt_opts = mnt->mnt_opts; 176 177 /* 178 * Solaris 2.5 and newer take a second argument to gettimeofday(). If you 179 * find a useful svr4-like OS that uses the old style, and this code here 180 * fails, then create a new autoconf test that will determine the number 181 * of arguments gettimeofday() takes. -Erez. 182 */ 183 if (gettimeofday(&tv, NULL) < 0) 184 timestr[0] = '\0'; 185 else 186 xsnprintf(timestr, sizeof(timestr), "%ld", tv.tv_sec); 187 188 mt.mnt_time = timestr; 189 190 return &mt; 191} 192#endif /* MOUNT_TABLE_ON_FILE */ 193 194 195static void 196write_mntent_to_mtab(FILE *fp, const mntent_t *mnt) 197{ 198#ifdef MOUNT_TABLE_ON_FILE 199 putmntent(fp, update_mnttab_fields(mnt)); 200#endif /* MOUNT_TABLE_ON_FILE */ 201} 202 203 204/****************************************************************************/ 205/*** Public functions */ 206/****************************************************************************/ 207 208 209void 210unlock_mntlist(void) 211{ 212 unlockmnttab(); 213} 214 215 216/* 217 * Read a mount table into memory 218 */ 219mntlist * 220read_mtab(char *fs, const char *mnttabname) 221{ 222 mntlist **mpp, *mhp; 223 FILE *fp; 224 mntent_t mountbuf; 225 int ret; 226 227 if (lockmnttab() < 0) /* failed locking */ 228 return NULL; 229 230 fp = fopen(mnttabname, "r"); 231 if (fp == NULL) { 232 plog(XLOG_ERROR, "Can't open %s: %m", mnttabname); 233 return NULL; 234 } 235 mpp = &mhp; 236 237 while ((ret = getmntent(fp, &mountbuf)) == 0) { 238 /* 239 * Allocate a new slot 240 */ 241 *mpp = ALLOC(struct mntlist); 242 243 /* 244 * Copy the data returned by getmntent 245 */ 246 (*mpp)->mnt = mnt_dup(&mountbuf); 247 248 /* 249 * Move to next pointer 250 */ 251 mpp = &(*mpp)->mnext; 252 } 253 254 if (ret > 0) { 255 plog(XLOG_ERROR, "read error on %s: %m", mnttabname); 256 unlockmnttab(); 257 mhp = NULL; 258 } 259 *mpp = NULL; 260 261 fclose(fp); 262 return mhp; 263} 264 265 266void 267rewrite_mtab(mntlist *mp, const char *mnttabname) 268{ 269 FILE *fp; 270 271 assert(mntent_lock_fd >= 0); /* ensure lock fd is valid */ 272 273 fp = fopen(mnttabname, "r+"); 274 if (fp == NULL) { 275 plog(XLOG_ERROR, "Can't open %s: %m", mnttabname); 276 unlockmnttab(); 277 return; 278 } 279 while (mp) { 280 if (mp->mnt) 281 write_mntent_to_mtab(fp, mp->mnt); 282 mp = mp->mnext; 283 } 284 285 ftruncate(fileno(fp), ftell(fp)); 286 fclose(fp); 287 unlockmnttab(); 288} 289 290 291void 292write_mntent(mntent_t *mtp, const char *mnttabname) 293{ 294 FILE *fp; 295 296 if (lockmnttab() < 0) 297 return; 298 299 fp = fopen(mnttabname, "a"); 300 if (fp == NULL) { 301 plog(XLOG_ERROR, "Unable to append %s: %m", mnttabname); 302 return; 303 } 304 write_mntent_to_mtab(fp, mtp); 305 306 fclose(fp); 307 unlockmnttab(); 308} 309