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 (c) 1999 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <errno.h> 32 #include <syslog.h> 33 #include <libintl.h> 34 #include <unistd.h> 35 #include <strings.h> 36 #include <string.h> 37 #include <assert.h> 38 #include <stdlib.h> 39 #include "nfslogd.h" 40 #include "../lib/nfslogtab.h" 41 #include "buffer_list.h" 42 43 static int buildbuffer_list(struct buffer_ent **, timestruc_t *); 44 static void free_buffer_ent(struct buffer_ent *); 45 static struct buffer_ent *findbuffer(struct buffer_ent *, char *); 46 static void free_sharepnt_list(struct sharepnt_ent *); 47 static void free_sharepnt_ent(struct sharepnt_ent *); 48 #ifdef DEBUG 49 static void print_sharepnt_list(struct sharepnt_ent *); 50 #endif 51 static struct sharepnt_ent *findsharepnt(struct sharepnt_ent *, char *, 52 struct sharepnt_ent **); 53 54 /* 55 * Builds the buffer list from NFSLOGTAB and returns it in *listpp. 56 * Returns 0 on success, non-zero error code otherwise. 57 */ 58 int 59 getbuffer_list(struct buffer_ent **listpp, timestruc_t *lu) 60 { 61 *listpp = NULL; 62 return (buildbuffer_list(listpp, lu)); 63 } 64 65 /* 66 * If NFSLOGTAB has not been modified since the last time we read it, 67 * it simply returns the same buffer list, otherwise it re-reads NFSLOGTAB 68 * and rebuilds the list. 69 * No NFSLOGTAB is not treated as an error. 70 * Returns 0 on success, non-zero error code otherwise 71 */ 72 int 73 checkbuffer_list(struct buffer_ent **listpp, timestruc_t *lu) 74 { 75 struct stat st; 76 int error = 0; 77 78 if (stat(NFSLOGTAB, &st) == -1) { 79 error = errno; 80 if (error != ENOENT) { 81 syslog(LOG_ERR, gettext("Can't stat %s - %s"), 82 NFSLOGTAB, strerror(error)); 83 error = 0; 84 } 85 return (error); 86 } 87 88 if (lu->tv_sec == st.st_mtim.tv_sec && 89 lu->tv_nsec == st.st_mtim.tv_nsec) 90 return (0); 91 92 free_buffer_list(listpp); /* free existing list first */ 93 return (buildbuffer_list(listpp, lu)); 94 } 95 96 /* 97 * Does the actual work of reading NFSLOGTAB, and building the 98 * buffer list. If *be_head already contains entries, it will 99 * update the list with new information. 100 * Returns 0 on success, non-zero error code otherwise. 101 */ 102 static int 103 buildbuffer_list(struct buffer_ent **be_head, timestruc_t *lu) 104 { 105 FILE *fd; 106 struct buffer_ent *be_tail = NULL, *bep; 107 struct sharepnt_ent *se_tail = NULL, *sep; 108 struct logtab_ent *lep; 109 struct stat st; 110 int error = 0, res; 111 112 if ((fd = fopen(NFSLOGTAB, "r+")) == NULL) { 113 error = errno; 114 if (error != ENOENT) { 115 syslog(LOG_ERR, gettext("%s - %s\n"), NFSLOGTAB, 116 strerror(error)); 117 error = 0; 118 } 119 return (error); 120 } 121 122 if (lockf(fileno(fd), F_LOCK, 0L) < 0) { 123 error = errno; 124 syslog(LOG_ERR, gettext("cannot lock %s - %s\n"), NFSLOGTAB, 125 strerror(error)); 126 (void) fclose(fd); 127 return (error); 128 } 129 130 assert(*be_head == NULL); 131 while ((res = logtab_getent(fd, &lep)) > 0) { 132 if (bep = findbuffer(*be_head, lep->le_buffer)) { 133 /* 134 * Add sharepnt to buffer list 135 */ 136 if (sep = findsharepnt(bep->be_sharepnt, 137 lep->le_path, &se_tail)) { 138 /* 139 * Sharepoint already in list, 140 * update its state. 141 */ 142 sep->se_state = lep->le_state; 143 } else { 144 /* 145 * Need to add to sharepoint list 146 */ 147 sep = (struct sharepnt_ent *) 148 malloc(sizeof (*sep)); 149 if (sep == NULL) { 150 error = ENOMEM; 151 goto errout; 152 } 153 (void) memset(sep, 0, sizeof (*sep)); 154 155 sep->se_name = strdup(lep->le_path); 156 if (sep->se_name == NULL) { 157 error = ENOMEM; 158 goto errout; 159 } 160 sep->se_state = lep->le_state; 161 162 assert(se_tail != NULL); 163 assert(se_tail->se_next == NULL); 164 se_tail->se_next = sep; 165 } 166 } else { 167 /* 168 * Add new buffer to list 169 */ 170 bep = (struct buffer_ent *)malloc(sizeof (*bep)); 171 if (bep == NULL) { 172 error = ENOMEM; 173 goto errout; 174 } 175 (void) memset(bep, 0, sizeof (*bep)); 176 177 bep->be_name = strdup(lep->le_buffer); 178 if (bep->be_name == NULL) { 179 error = ENOMEM; 180 goto errout; 181 } 182 183 if (*be_head == NULL) 184 *be_head = bep; 185 else 186 be_tail->be_next = bep; 187 be_tail = bep; 188 189 bep->be_sharepnt = (struct sharepnt_ent *) 190 malloc(sizeof (*(bep->be_sharepnt))); 191 (void) memset(bep->be_sharepnt, 0, 192 sizeof (*(bep->be_sharepnt))); 193 194 if (bep->be_sharepnt == NULL) { 195 error = ENOMEM; 196 goto errout; 197 } 198 bep->be_sharepnt->se_name = strdup(lep->le_path); 199 if (bep->be_sharepnt->se_name == NULL) { 200 error = ENOMEM; 201 goto errout; 202 } 203 bep->be_sharepnt->se_state = lep->le_state; 204 } 205 } 206 207 if (res < 0) { 208 error = EIO; 209 goto errout; 210 } 211 212 /* 213 * Get modification time while we have the file locked. 214 */ 215 if (lu) { 216 if ((error = fstat(fileno(fd), &st)) == -1) { 217 syslog(LOG_ERR, gettext("Can't stat %s"), NFSLOGTAB); 218 goto errout; 219 } 220 *lu = st.st_mtim; 221 } 222 223 (void) fclose(fd); 224 return (error); 225 226 errout: 227 (void) fclose(fd); 228 if (lep) 229 logtab_ent_free(lep); 230 free_buffer_list(be_head); 231 assert(*be_head == NULL); 232 syslog(LOG_ERR, gettext("cannot read %s: %s\n"), NFSLOGTAB, 233 strerror(error)); 234 235 return (error); 236 } 237 238 /* 239 * Removes the entry from the buffer list and frees it. 240 */ 241 void 242 remove_buffer_ent(struct buffer_ent **be_listpp, struct buffer_ent *bep) 243 { 244 struct buffer_ent *p, *prev; 245 246 for (p = prev = *be_listpp; p != NULL; p = p->be_next) { 247 if (p == bep) { 248 if (p == *be_listpp) 249 *be_listpp = (*be_listpp)->be_next; 250 else 251 prev->be_next = bep->be_next; 252 free_buffer_ent(bep); 253 break; 254 } 255 prev = p; 256 } 257 } 258 259 /* 260 * Frees the buffer list. 261 */ 262 void 263 free_buffer_list(struct buffer_ent **be_listpp) 264 { 265 struct buffer_ent *bep, *nextp; 266 267 for (bep = *be_listpp; bep != NULL; bep = nextp) { 268 nextp = bep->be_next; 269 free_buffer_ent(bep); 270 } 271 *be_listpp = NULL; 272 } 273 274 static void 275 free_buffer_ent(struct buffer_ent *bep) 276 { 277 assert(bep != NULL); 278 if (debug) 279 (void) printf("freeing %s\n", bep->be_name); 280 if (bep->be_name != NULL) 281 free(bep->be_name); 282 if (bep->be_sharepnt != NULL) 283 free_sharepnt_list(bep->be_sharepnt); 284 free(bep); 285 } 286 287 static void 288 free_sharepnt_list(struct sharepnt_ent *sep_listp) 289 { 290 struct sharepnt_ent *nextp; 291 292 for (; sep_listp != NULL; sep_listp = nextp) { 293 nextp = sep_listp->se_next; 294 free_sharepnt_ent(sep_listp); 295 } 296 free(sep_listp); 297 } 298 299 /* 300 * Removes the entry from the sharepnt list and frees it. 301 */ 302 void 303 remove_sharepnt_ent(struct sharepnt_ent **se_listpp, struct sharepnt_ent *sep) 304 { 305 struct sharepnt_ent *p, *prev; 306 307 for (p = prev = *se_listpp; p != NULL; p = p->se_next) { 308 if (p == sep) { 309 if (p == *se_listpp) 310 *se_listpp = (*se_listpp)->se_next; 311 else 312 prev->se_next = sep->se_next; 313 free_sharepnt_ent(sep); 314 break; 315 } 316 prev = p; 317 } 318 } 319 320 static void 321 free_sharepnt_ent(struct sharepnt_ent *sep) 322 { 323 assert(sep != NULL); 324 if (debug) 325 (void) printf("freeing %s\n", sep->se_name); 326 if (sep->se_name != NULL) 327 free(sep->se_name); 328 free(sep); 329 } 330 331 #ifdef DEBUG 332 void 333 printbuffer_list(struct buffer_ent *bep) 334 { 335 for (; bep != NULL; bep = bep->be_next) { 336 (void) printf("%s\n", bep->be_name); 337 if (bep->be_sharepnt != NULL) 338 print_sharepnt_list(bep->be_sharepnt); 339 } 340 } 341 342 static void 343 print_sharepnt_list(struct sharepnt_ent *sep) 344 { 345 for (; sep != NULL; sep = sep->se_next) 346 (void) printf("\t(%d) %s\n", sep->se_state, sep->se_name); 347 } 348 #endif 349 350 /* 351 * Returns a pointer to the buffer matching 'name', NULL otherwise. 352 */ 353 static struct buffer_ent * 354 findbuffer(struct buffer_ent *bep, char *name) 355 { 356 for (; bep != NULL; bep = bep->be_next) { 357 if (strcmp(bep->be_name, name) == 0) 358 return (bep); 359 } 360 return (NULL); 361 } 362 363 /* 364 * Returns a pointer the sharepoint entry matching 'name'. 365 * Otherwise, it sets '*se_tail' to the last element of the list 366 * to make insertion of new element easier, and returns NULL. 367 */ 368 static struct sharepnt_ent * 369 findsharepnt( 370 struct sharepnt_ent *sep, 371 char *name, 372 struct sharepnt_ent **se_tail) 373 { 374 struct sharepnt_ent *tail; 375 376 for (; sep != NULL; sep = sep->se_next) { 377 if (strcmp(sep->se_name, name) == 0) 378 return (sep); 379 tail = sep; 380 } 381 *se_tail = tail; 382 return (NULL); 383 } 384