1 /* $NetBSD: mtab_svr4.c,v 1.1.1.2 2009/03/20 20:26:50 christos Exp $ */ 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 */ 60 static int mntent_lock_fd = -1; 61 62 63 #ifdef MOUNT_TABLE_ON_FILE 64 static char mtlckname[] = "/etc/.mnttab.lock"; 65 #endif /* MOUNT_TABLE_ON_FILE */ 66 67 68 /****************************************************************************/ 69 /*** Private functions */ 70 /****************************************************************************/ 71 72 static void 73 unlockmnttab(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 85 static int 86 lockfile(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 */ 107 static int 108 lockmnttab(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 */ 145 static mntent_t * 146 mnt_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 164 static mntent_t * 165 update_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 195 static void 196 write_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 209 void 210 unlock_mntlist(void) 211 { 212 unlockmnttab(); 213 } 214 215 216 /* 217 * Read a mount table into memory 218 */ 219 mntlist * 220 read_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 266 void 267 rewrite_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 291 void 292 write_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