mountd.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 2,539 行 · 第 1/5 页

C
2,539
字号
 		if ((ch1 && ch2) && !strcmp(ch1, ch2)) { 			if (ch11 && *ch11 != '\0') { 				*--ch11 = s1; 				ch11++; 			} 			if (ch22 && *ch22 != '\0') { 				*--ch22 = s2; 				ch22++; 			} 			ch1 = ch11; 			ch2 = ch22; 			if ((ch11 && *ch11 == '\0') || !ch11) {				/*				 * count number of slashes remaining in ancestor				 */				if (ch2) {					for (--ch2; ch2 && *ch2!='\0'; ch2++)						if (*ch2 == '/') level++;					if (*--ch2 == '/')						level--;				} 				return(level);			} 			if ((ch11 && *ch11 != '\0') && ((ch22 && *ch22 == '\0') || !ch22)) 				done = 1; 		} 		else { 			if (ch11 && *ch11 != '\0') 				*--ch11 = s1; 			if (ch22 && *ch22 != '\0') 				*--ch22 = s2; 			done = 1; 		} 	}	return(level);}/* * Skip over slashes (/) and go to first character */char *goto_char(ch) 	char *ch;{ 	for (;ch && *ch == '/'; ch++) 		;	if (ch) 		return(ch);	else		return(NULL);} /* * Remove an entry from mounted list */mtd_umount(rqstp, transp)	struct svc_req *rqstp;	SVCXPRT *transp;{	char *path;	struct mountdlist *ml, *oldml;	struct hostent *client;	long pos = -1;        if ((client = getclientsname(rqstp,transp))== NULL) {                svcerr_weakauth(transp);                return;        }	path = NULL;	if (!svc_getargs(transp, xdr_path, &path)) {		svcerr_decode(transp);		mtd_abort();		return;	}#ifdef DEBUG	(void) fprintf(stderr, "umounting %s for %s\n", path, client->h_name);#endif	oldml = mountlist;	for (ml = mountlist; ml != NULL;	    oldml = ml, ml = ml->ml_nxt) {		if (strcmp(ml->ml_path, path) == 0 &&		    strcmp(ml->ml_name, client->h_name) == 0) {			if (ml == mountlist)				mountlist = ml->ml_nxt;			else				oldml->ml_nxt = ml->ml_nxt;#ifdef DEBUG			(void) fprintf(stderr, "freeing %s\n", path);#endif			pos = ml->ml_pos;			free(ml->ml_path);			free(ml->ml_name);			free((char *)ml);			break;		    }	}	if (!svc_sendreply(transp,xdr_void, NULL)) {		syslog(LOG_ERR, "couldn't reply to UMOUNT rpc call");		mtd_abort();	} else {		gettimeofday(&now, &tz);                if ((now.tv_sec - rmtab_written.tv_sec) > rmtab_sync) {                        dumptofile();                        rmtab_written = now;                }                else if (pos >= 0) {                        rmtab_delete(pos);                }	}	svc_freeargs(transp, xdr_path, &path);}/* * Remove all entries for one machine from mounted list */mtd_umountall(rqstp, transp)	struct svc_req *rqstp;	SVCXPRT *transp;{	char *machine;	struct mountdlist *ml, *oldml;	if (!svc_getargs(transp, xdr_void, NULL)) {		svcerr_decode(transp);		return;	}	/*	 * We assume that this call is asynchronous and made via the 	 * portmapper callit routine.  Therefore return control immediately.	 * The error causes the portmapper to remain silent, as opposed to	 * every machine on the net blasting the requester with a response.	 */	svcerr_systemerr(transp);        if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {                machine =                   ((struct authunix_parms *)rqstp->rq_clntcred)->aup_machname;        }        else                return;	oldml = mountlist;	for (ml = mountlist; ml != NULL; ml = ml->ml_nxt) {		if (strncmp(ml->ml_name, machine, sizeof(machine)) == 0) {#ifdef DEBUG			(void) fprintf(stderr, "got a hit\n");#endif			if (ml == mountlist) {				mountlist = ml->ml_nxt;				oldml = mountlist;			}			else				oldml->ml_nxt = ml->ml_nxt;			rmtab_delete(ml->ml_pos);			free(ml->ml_path);			free(ml->ml_name);			free((char *)ml);		}		else			oldml = ml;	}	svc_freeargs(transp, xdr_void, NULL);}FILE *f;/* * Save current mount state info so we * can attempt to recover in case of a crash. */dumptofile(){	static char *t1 = "/etc/zzXXXXXX";	static char *t2 = "/etc/zzXXXXXX";	FILE *fp;	struct mountdlist *ml;	char *mktemp();	int mf;		(void) fclose(f);	(void) strcpy(t2, t1);	t2 = mktemp(t2);	if ((mf = creat(t2, 0644)) < 0) {		syslog(LOG_ERR, "creat: %m, cannot dump mountlist to %s", RMTAB);		return;	}	if ((fp = fdopen(mf, "w")) == NULL) {		syslog(LOG_ERR, "fdopen: %m, cannot dump mountlist to %s", RMTAB);		return;	}	for (ml = mountlist; ml != NULL; ml = ml->ml_nxt) {		ml->ml_pos = ftell(fp);		(void) fprintf(fp, "%s:%s\n", ml->ml_name, ml->ml_path);	}	if (rename(t2, RMTAB) < 0) 		syslog(LOG_ERR, "rename: %m, cannot dump mountlist to %s", RMTAB);	(void) fclose(fp);	 f = fopen(RMTAB, "r+");}/* * send current export list */mtd_export(transp)	SVCXPRT *transp;{	struct exports *ex;	if (!svc_getargs(transp, xdr_void, NULL)) {		svcerr_decode(transp);		mtd_abort();	} else {		/*		 * Send exported request the list of flattened exports		 * to conform with other os's.  Otherwise, all 		 * exported directories would not be seen.		 */		ex = flatexports;		if (!svc_sendreply(transp, xdr_exports, &ex)) {			syslog(LOG_ERR, "couldn't reply to EXPORT rpc call");			mtd_abort();		}	}}/* * Parse exports file.  If this is the first call or the file exportfile * has changed, it is opened and parsed to create an exports list. * File should look like: * * pathname [-r=#] [-o] [name1 name2 ... namen] *   or * #anything * * pathname:	name of a mounted local file system *		name of a directory of a mounted local filesystem * optional options *	 -r=#	for entire filesystem, root maps to # *	 -o	entire filesystem exported readonly * name:	netgroup or host name or a list of whitespace separated *			names (optional, no names implies everyone) * * A '#' anywhere in the line marks a comment to the end of that line * * NOTE: a non-white character in column 1 indicates a new export *	specification. */set_exports(){	int bol;	/* begining of line */	int eof;	/* end of file */	int opt;	/* beginning of option */	struct exports *ex, *ex2;	int newdev();	char ch;	char *str;	char *l;	char line[MAXLINE];	/* current line */	struct stat statb;	FILE *fp;	int isdev;	int found;	int bad_entry=0;  /* true if current entry does not exist or is a duplicate */	if (stat(exportfile, &statb) < 0) {#ifdef DEBUG		(void) fprintf(stderr, "%s: stat failed", pgmname);		perror("mountd: exportfile");#endif		freeex(exports);		exports = NULL;		freeex(flatexports);		flatexports = NULL;		return;	}	if (exportstat.st_mtime == statb.st_mtime) {		return;	}	exportstat = statb;	if ((fp = fopen(exportfile, "r")) == NULL) {		syslog(LOG_ERR, "fopen: %m");		freeex(exports);		exports = NULL;		freeex(flatexports);		flatexports = NULL;		return;	}	dupcache_inval();               /* invalidate the dup req cache */	freeex(exports);	exports = NULL;	freeex(flatexports);	flatexports = NULL;	eof = 0;	l = line;	*l = '\0';	while (!eof) {		switch (*l) {		case '\0':		case '\n':			/*			 * End of line, read next line and set state vars			 */			if (fgets(line, MAXLINE, fp) == NULL) {				eof = 1;			} else {				bol = 1;				opt = 0;				l = line;			}			break;		case ' ':		case '	':			/*			 * If this is the continuation of a bad entry, skip the line			 */			if (bad_entry) {				*l = '\0';				break;			}			/*			 * White space, skip to first non-white			 */			while (*l == ' ' || *l == '	') {				l++;			}			bol = 0;			break;		case '#':			/*			 * Comment, skip to end of line.			 */			*l = '\0';			break;		case '-':			/*			 * option of the form: -option=value or -option			 */			if (bol) {				syslog(LOG_ERR, "Cannot parse '%s'", l);				*l = '\0';				break;			}			opt = 1;			l++;			break;		default:			/*			 * normal character: if col one get dir else name or opt			 */			str = l;			while (*l != ' ' && *l != '	' &&			     *l != '\0' && *l != '\n') {				l++;			}			ch = *l;			*l = '\0';			if (bol) {				/*				 * Logic for building export list:				 *  The list is organized by dev horizontally,				 *  all entries of the same dev hang off vertically.				 *  The top dev entry is just the first one read.				 *				 *  Try to find an exports list entry with the				 *  same dev number.  If not found, this entry				 *  represents a new top entry.  Connect its				 *  devptr to the front of the exports list.				 *  If a dev match was found, tack this entry on				 *  to the "next" pointer of the top entry for this 				 *  dev.  Always check if this is a duplicate entry.				 */#ifdef DEBUG_FULL				(void) fprintf(stderr, "--- next /etc/exports entry to add is %s ---\n", str);#endif DEBUG_FULL				bad_entry = 0;  /* this is a new export entry */				if (stat(str, &statb) < 0) {					syslog(LOG_ERR, "stat: %m, Cannot stat %s", str);					bad_entry = 1;					break;				}				for (ex = exports; ex != NULL; ex = ex->ex_devptr) 					if (ex->ex_dev == statb.st_dev) break;				if (ex == NULL) {					isdev = TRUE;#ifdef DEBUG_FULL					(void) fprintf(stderr, "adding new export %s\n", str);#endif DEBUG_FULL					newdev(str, statb.st_dev, statb.st_ino, statb.st_gennum);					ex = exports;				}				else {					found = FALSE;					for (ex2=ex; ex2 != NULL; ex2 = ex2->ex_next)						if (ex2->ex_ino == statb.st_ino) {							syslog(LOG_ERR, "Duplicate directory entry for %s - duplicate ignored", str); 							found = TRUE;							bad_entry = 1;							break;						}					if (!found) {						isdev = FALSE;						/*					  	   initialize rootmap to nobody and flags to 0						*/#ifdef DEBUG_FULL						(void) fprintf(stderr, "adding new export %s\n", str);#endif DEBUG_FULL						ex->ex_next = newex(str, ex->ex_next, statb.st_dev, statb.st_ino, statb.st_gennum, -2, 0);					}					else 						break;  /* skip rest of entry */				}			}			else {				if (opt) {					opt = 0;					if (isdev) 						setopt(str, ex);					else 						setopt(str, ex->ex_next);				}				else {					if (!isdev) {#ifdef DEBUG_FULL						(void) fprintf(stderr, "adding new groups %s to %s\n", str, ex->ex_next->ex_name);#endif DEBUG_FULL						ex->ex_next->ex_groups = newgroup(str, ex->ex_next->ex_groups);					}					else {#ifdef DEBUG_FULL						(void) fprintf(stderr, "adding new groups %s to %s\n", str, ex->ex_name);#endif DEBUG_FULL						ex->ex_groups = newgroup(str, ex->ex_groups);					}				}			}			*l = ch;			bol = 0;			break;		}	}	(void) fclose(fp);#ifdef DEBUG	(void) fprintf(stderr, "*** export list final results ***\n");	print_exports(exports);#endif DEBUG	/*	 * Update the kernel's exportfsdata list so that it is in sync with	 * the exports file and the mountd's list.	 */	update_exportfsdata();	flatten_exports();#ifdef DEBUG_FULL	(void) fprintf(stderr, "*** export list final results flattened ***\n");	print_exports(flatexports);#endif DEBUG_FULL	return;}/* * Make exportfs calls necessary to update kernel's view of exports. */update_exportfsdata(){	struct exports *ex, *ex2, *k_ex=NULL, *k_ptr;	struct exportfsdata kbuf;	u_int cookie=0;	/*	 * Build a list equivalent to kernel's list.	 */	for (;;) {		if ((exportfs (EXPORTFS_READ, &cookie, &kbuf)) < 0) {			if (errno == ENOENT) break;			syslog(LOG_ERR, "exportfs READ: %m");			exit (1);		}		k_ex = newex(kbuf.e_path, k_ex, kbuf.e_fsid, kbuf.e_gnum, kbuf.e_gen, kbuf.e_rootmap, kbuf.e_flags);		if (kbuf.e_more == 0) break;	}#ifdef DEBUG_FULL 	(void) fprintf (stderr, "*** Kernel exportfsdata before changes ***\n");	print_exports(k_ex);#endif DEBUG_FULL  	/*	 * Loop through mountd's export list.  Find matching entry in	 * local view of kernel's exportfsdata list.  If one is not found,	 * add this export to kernel's list.  If they are different,	 * update the kernel's data.  Mark the k_ex entry that has 	 * been looked at so that we know what hasn't been checked yet.	 */	 for (ex=exports; ex!=NULL; ex=ex->ex_devptr) {		for (ex2=ex; ex2!=NULL; ex2=ex2->ex_next) {			/*			   find matching kernel entry			*/			for (k_ptr=k_ex; k_ptr!=NULL; k_ptr=k_ptr->ex_next)				if ((strcmp(k_ptr->ex_name, ex2->ex_name))==0) break;			/*

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?