1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1999 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * Portions of this source code were derived from Berkeley 4.3 BSD 32 * under license from the Regents of the University of California. 33 */ 34 35 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 #include "sharetab.h" 42 43 static int logging_specified(char *); 44 45 /* 46 * Get an entry from the share table. 47 * There should be at least 4 fields: 48 * 49 * pathname resource fstype options [ description ] 50 * 51 * A fifth field (description) is optional. 52 * 53 * Returns: 54 * > 1 valid entry 55 * = 0 end of file 56 * < 0 error 57 */ 58 int 59 getshare(fd, shp) 60 FILE *fd; 61 struct share **shp; 62 { 63 static char *line = NULL; 64 static struct share *sh = NULL; 65 char *p; 66 char *lasts; 67 char *w = " \t"; 68 69 if (line == NULL) { 70 line = (char *)malloc(MAXBUFSIZE+1); 71 if (line == NULL) 72 return (-1); 73 } 74 if (sh == NULL) { 75 sh = (struct share *)malloc(sizeof (*sh)); 76 if (sh == NULL) 77 return (-1); 78 } 79 80 p = fgets(line, MAXBUFSIZE, fd); 81 if (p == NULL) 82 return (0); 83 line[strlen(line) - 1] = '\0'; 84 85 sh->sh_path = (char *)strtok_r(p, w, &lasts); 86 if (sh->sh_path == NULL) 87 return (-3); 88 sh->sh_res = (char *)strtok_r(NULL, w, &lasts); 89 if (sh->sh_res == NULL) 90 return (-3); 91 sh->sh_fstype = (char *)strtok_r(NULL, w, &lasts); 92 if (sh->sh_fstype == NULL) 93 return (-3); 94 sh->sh_opts = (char *)strtok_r(NULL, w, &lasts); 95 if (sh->sh_opts == NULL) 96 return (-3); 97 sh->sh_descr = (char *)strtok_r(NULL, "", &lasts); 98 if (sh->sh_descr == NULL) 99 sh->sh_descr = ""; 100 101 *shp = sh; 102 return (1); 103 } 104 105 /* 106 * Append an entry to the sharetab file. 107 */ 108 int 109 putshare(fd, sh) 110 FILE *fd; 111 struct share *sh; 112 { 113 int r; 114 115 if (fseek(fd, 0L, 2) < 0) 116 return (-1); 117 118 r = fprintf(fd, "%s\t%s\t%s\t%s\t%s\n", 119 sh->sh_path, 120 sh->sh_res, 121 sh->sh_fstype, 122 sh->sh_opts, 123 sh->sh_descr); 124 return (r); 125 } 126 127 /* 128 * The entry corresponding to path is removed from the 129 * sharetab file. The file is assumed to be locked. 130 * Read the entries into a linked list of share structures 131 * minus the entry to be removed. Then truncate the sharetab 132 * file and write almost all of it back to the file from the 133 * linked list. 134 * 135 * If logging information is requested then 'logging' is set 136 * to non-zero if the entry is shared with logging enabled. 137 * 138 * Note: The file is assumed to be locked. 139 */ 140 int 141 remshare(fd, path, logging) 142 FILE *fd; 143 char *path; 144 int *logging; 145 { 146 struct share *sh_tmp; 147 struct shl { /* the linked list */ 148 struct shl *shl_next; 149 struct share *shl_sh; 150 }; 151 struct shl *shl_head = NULL; 152 struct shl *shl, *prev, *next; 153 int res, remcnt; 154 155 rewind(fd); 156 remcnt = 0; 157 shl = NULL; 158 while ((res = getshare(fd, &sh_tmp)) > 0) { 159 if (strcmp(path, sh_tmp->sh_path) == 0 || 160 strcmp(path, sh_tmp->sh_res) == 0) { 161 remcnt++; 162 if (logging != NULL) 163 *logging = logging_specified(sh_tmp->sh_opts); 164 } else { 165 prev = shl; 166 shl = (struct shl *)malloc(sizeof (*shl)); 167 if (shl == NULL) { 168 res = -1; 169 goto dealloc; 170 } 171 if (shl_head == NULL) 172 shl_head = shl; 173 else 174 prev->shl_next = shl; 175 shl->shl_next = NULL; 176 shl->shl_sh = sharedup(sh_tmp); 177 if (shl->shl_sh == NULL) { 178 res = -3; 179 goto dealloc; 180 } 181 } 182 } 183 if (res < 0) 184 goto dealloc; 185 if (remcnt == 0) { 186 res = 1; /* nothing removed */ 187 goto dealloc; 188 } 189 190 if (ftruncate(fileno(fd), 0) < 0) { 191 res = -2; 192 goto dealloc; 193 } 194 195 for (shl = shl_head; shl; shl = shl->shl_next) 196 putshare(fd, shl->shl_sh); 197 res = 1; 198 199 dealloc: 200 for (shl = shl_head; shl; shl = next) { 201 /* 202 * make sure we don't reference sharefree with NULL shl->shl_sh 203 */ 204 if (shl->shl_sh != NULL) 205 sharefree(shl->shl_sh); 206 next = shl->shl_next; 207 free(shl); 208 } 209 return (res); 210 } 211 212 struct share * 213 sharedup(sh) 214 struct share *sh; 215 { 216 struct share *nsh; 217 218 nsh = (struct share *)malloc(sizeof (*nsh)); 219 if (nsh == NULL) 220 return (NULL); 221 222 (void) memset((char *)nsh, 0, sizeof (*nsh)); 223 if (sh->sh_path) { 224 nsh->sh_path = strdup(sh->sh_path); 225 if (nsh->sh_path == NULL) 226 goto alloc_failed; 227 } 228 229 if (sh->sh_res) { 230 nsh->sh_res = strdup(sh->sh_res); 231 if (nsh->sh_res == NULL) 232 goto alloc_failed; 233 } 234 if (sh->sh_fstype) { 235 nsh->sh_fstype = strdup(sh->sh_fstype); 236 if (nsh->sh_fstype == NULL) 237 goto alloc_failed; 238 } 239 if (sh->sh_opts) { 240 nsh->sh_opts = strdup(sh->sh_opts); 241 if (nsh->sh_opts == NULL) 242 goto alloc_failed; 243 } 244 if (sh->sh_descr) { 245 nsh->sh_descr = strdup(sh->sh_descr); 246 if (nsh->sh_descr == NULL) 247 goto alloc_failed; 248 } 249 return (nsh); 250 251 alloc_failed: 252 sharefree(nsh); 253 return (NULL); 254 } 255 256 void 257 sharefree(sh) 258 struct share *sh; 259 { 260 if (sh->sh_path != NULL) 261 free(sh->sh_path); 262 if (sh->sh_res != NULL) 263 free(sh->sh_res); 264 if (sh->sh_fstype != NULL) 265 free(sh->sh_fstype); 266 if (sh->sh_opts != NULL) 267 free(sh->sh_opts); 268 if (sh->sh_descr != NULL) 269 free(sh->sh_descr); 270 free(sh); 271 } 272 273 /* 274 * Return the value after "=" for option "opt" 275 * in option string "optlist". Caller must 276 * free returned value. 277 */ 278 char * 279 getshareopt(optlist, opt) 280 char *optlist, *opt; 281 { 282 char *p, *pe; 283 char *b; 284 char *bb; 285 char *lasts; 286 char *val = NULL; 287 288 b = bb = strdup(optlist); 289 if (b == NULL) 290 return (NULL); 291 292 while (p = (char *)strtok_r(b, ",", &lasts)) { 293 b = NULL; 294 if (pe = strchr(p, '=')) { 295 *pe = '\0'; 296 if (strcmp(opt, p) == 0) { 297 val = strdup(pe + 1); 298 goto done; 299 } 300 } 301 if (strcmp(opt, p) == 0) { 302 val = strdup(""); 303 goto done; 304 } 305 } 306 done: 307 free(bb); 308 return (val); 309 } 310 311 /* 312 * Return 1 if the "log" option was specified in the optlist. 313 * Return 0 otherwise. 314 */ 315 static int 316 logging_specified(optlist) 317 char *optlist; 318 { 319 char *p; 320 char *b, *bb, *lasts; 321 int specified = 0; 322 323 b = bb = strdup(optlist); 324 if (b == NULL) 325 return (0); 326 327 while (p = (char *)strtok_r(b, ",", &lasts)) { 328 b = NULL; 329 if (strncmp(p, "log", 3) == 0) 330 specified++; 331 } 332 333 free(bb); 334 return (specified ? 1 : 0); 335 } 336