⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tfs_dirs.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			       first_sub_layer);	}	for (i = first_sub_layer; i <= MAX_SUB_LAYER; i++) {		if (front_pnodes[i] == NULL) {			continue;		}		if (write_backlist(front_pnodes[i], backlists[i])) {			nse_log_message(				"warning: can't write .tfs_backfiles");			print_pnode_path(front_pnodes[i]);		}	}error:	for (i = 0; i <= MAX_SUB_LAYER; i++) {		nse_hash_destroy(backhashs[i], (Nse_voidfunc) free,				 (Nse_voidfunc) NULL);		if (ro_pnodes[i] != NULL) {			free_pnode(ro_pnodes[i]);		}	}	destroy_backlists(ro_backlists);	return (result);}static bool_tbuild_backlist_one_layer(pp, sub_layer, backhashs, backlist)	struct pnode	*pp;	int		sub_layer;	Hash		*backhashs;	Nse_list	backlist;{	DIR		*dirp;	struct direct	*dp;	dirp = tfs_opendir(pp);	if (dirp == NULL) {		return (FALSE);	}	dp = readdir(dirp);	while (dp != NULL) {		if (good_name(dp->d_name)) {			(void) add_to_backlist_unique(backlist, backhashs,						      dp->d_name, 1,						      sub_layer, 0L);		}		dp = readdir(dirp);	}	tfs_closedir(dirp);	return (TRUE);}/* * Add the directory with pnode 'pp' to 'backlist'.  This routine exists * solely to prevent the runtime stack of build_backlists() from getting * too large in case we have to recurse a number of times.  Note that * we always put the directory names of the first read-only layer into the * backlist.  These directory names are needed by read_and_verify_backlists() * to determine whether or not a backlist is valid; and by * tfs_set_searchlink() to determine whether or not a new searchlink * is different from the one already set. */static voidadd_dir_to_backlist(pp, backlist)	struct pnode	*pp;	Nse_list	backlist;{	char		pn[MAXPATHLEN];	ptopn(pp, pn);	add_to_backlist(backlist, pn, 1, 0L);}static bool_thave_all_ro_backlists(ro_pnodes, ro_backlists, first_sub_layer)	struct pnode	**ro_pnodes;	Nse_list	*ro_backlists;	unsigned	first_sub_layer;{	int		i;	for (i = first_sub_layer; i <= MAX_SUB_LAYER; i++) {		if (ro_pnodes[i] == NULL || ro_backlists[i] == NULL) {			return (FALSE);		}	}	return (TRUE);}/* * Copy entries from backlists in sub-layers of the first read-only layer. */static voidcopy_backlists(backlists, backhashs, ro_backlists, first_sub_layer)	Nse_list	*backlists;	Hash		*backhashs;	Nse_list	*ro_backlists;	unsigned	first_sub_layer;{	bool_t		file_added;	int		i;	file_added = FALSE;	for (i = first_sub_layer; i <= MAX_SUB_LAYER; i++) {		nse_list_iterate(ro_backlists[i], copy_backlist_entry,				 backlists[i], backhashs, i, &file_added);	}}static voidcopy_backlist_entry(fl, backlist, backhashs, sub_layer, new_file)	Filelist	fl;	Nse_list	backlist;	Hash		*backhashs;	int		sub_layer;	bool_t		*new_file;{	if (!IS_DIRNAME(fl)) {		if (add_to_backlist_unique(backlist, backhashs, fl->fname,					   fl->layer + 1, sub_layer,					   fl->mtime)) {			*new_file = TRUE;		}	} else {		if (*new_file) {			add_to_backlist(backlist, fl->fname, fl->layer + 1,					fl->mtime);		}		*new_file = FALSE;	}}/* * Returns TRUE if 'fname' is added to the backlist; FALSE if the name * is already in the backlist.  Note that if 'fname' is in a variant * sub-layer, we must also make sure that 'fname' hasn't been added to * the shared-source backlist. */static bool_tadd_to_backlist_unique(backlist, backhashs, fname, layer, sub_layer, mtime)	Nse_list	backlist;	Hash		*backhashs;	char		*fname;	int		layer;	int		sub_layer;	long		mtime;{	char		*file_name;	int		i;	if (sub_layer < MAX_SUB_LAYER) {		for (i = MAX_SUB_LAYER; i > sub_layer; i--) {			if (nse_hash_lookup(backhashs[i], fname)) {				return (FALSE);			}		}	}	file_name = NSE_STRDUP(fname);	if (nse_hash_insert(backhashs[sub_layer], file_name, HASH_VALUE)) {		free(file_name);		return (FALSE);	}	add_to_backlist(backlist, fname, layer, mtime);	return (TRUE);}/* * 'backlists' is a list containing backlists for each of the sub-layers. * Convert the file and directory names in the backlists into child vnodes * and directory pnodes for the directory vnode 'pvp'. * 'pp' is the pnode of the last writeable layer. */static voidreaddir_backlists(pvp, pp, backlists, layer)	struct vnode	*pvp;	struct pnode	*pp;	Nse_list	*backlists;	int		layer;{	Flist_iter_rec	flist[MAX_SUB_LAYER + 1];	struct pnode	*next_pp;	unsigned	first_sub_layer = FIRST_SUBL(pvp);	int		max_sub_layer = MAX_SUB_LAYER;	int		min_layer;	unsigned	sub_layer;	int		i;	for (i = first_sub_layer; i <= MAX_SUB_LAYER; i++) {		if (backlists[i] == NULL) {			max_sub_layer = i - 1;			break;		}		flist[i].end = nse_list_end(backlists[i]);		flist[i].elem = nse_list_first_elem(backlists[i]);		flist[i].entry = (Filelist) nse_listelem_data(flist[i].elem);	}	while (1) {		layer++;		min_layer = INFINITY;		/*		 * Select the sub-layer with the minimum absolute layer #.		 */		for (i = first_sub_layer; i <= max_sub_layer; i++) {			if (!END_OF_LIST(flist[i]) &&			    flist[i].entry->layer < min_layer) {				min_layer = flist[i].entry->layer;				sub_layer = i;			}		}		if (min_layer == INFINITY) {			break;		}		/*		 * flist[sub_layer] now points to a series of file entries		 * followed by an entry for the directory in which the files		 * can be found.		 */		while (!IS_DIRNAME(flist[sub_layer].entry)) {			(void) create_child_vnode(pvp,					flist[sub_layer].entry->fname,					layer, flist[sub_layer].entry->mtime);			get_next_entry(&flist[sub_layer]);		}		/*		 * flist[sub_layer] now points to a directory entry.  If		 * layer == 0, then this is an extra directory name for		 * the first layer.  (Extra directory names used to exist		 * in the .tfs_backfiles of the frontmost sub-layer in		 * rev 3 backfiles.)		 * XXX remove this check when BACKF_VERSION changed.		 */		if (flist[sub_layer].entry->layer > 0) {			next_pp = path_to_pnode(flist[sub_layer].entry->fname,						sub_layer);			set_next_pnode(pvp, pp, next_pp, layer - 1);			pp = next_pp;		} else {			layer--;		}		get_next_entry(&flist[sub_layer]);	}	set_next_pnode(pvp, pp, (struct pnode *) NULL, layer - 1);}static voidget_next_entry(flist)	Flist_iter	flist;{	flist->elem = nse_listelem_next(flist->elem);	flist->entry = (Filelist) nse_listelem_data(flist->elem);}static voiddestroy_backlists(backlists)	Nse_list	*backlists;{	int		i;	for (i = 0; i <= MAX_SUB_LAYER; i++) {		if (backlists[i] != NULL) {			nse_list_destroy(backlists[i]);		}	}}/* * File 'name' has been seen in directory 'pvp' at layer # 'layer'.  Create * a vnode for the file if it hasn't been seen yet. */static struct vnode *create_child_vnode(pvp, name, layer, mtime)	struct vnode	*pvp;	char		*name;	int		layer;	long		mtime;{	struct vnode	*vp;	vp = find_vnode(pvp, name);	if (vp == NULL) {		vp = create_vnode(pvp, name, (long) 0);	}	if (vp->v_layer == INVALID_LAYER) {		vp->v_layer = layer;	} else if (vp->v_back_layer == INVALID_LAYER) {		vp->v_back_layer = layer;	}	vp->v_mtime = mtime;	return (vp);}/* * Create white-out vnodes for each of the entries in the whiteout list * 'wp'. */static voidcreate_whiteout_vnodes(pvp, layer, wp)	struct vnode	*pvp;	int		layer;	Nse_whiteout	wp;{	struct vnode	*vp;	while (wp != NULL) {		vp = find_vnode(pvp, wp->name);		if (vp == NULL) {			vp = create_vnode(pvp, wp->name, (long) 0);		}		if (vp->v_layer == INVALID_LAYER) {			vp->v_whited_out = TRUE;			vp->v_layer = layer;		} else if (vp->v_back_layer == INVALID_LAYER) {			vp->v_back_whited_out = TRUE;			vp->v_back_layer = layer;		}		wp = wp->next;	}}/* * Insert the entries in the whiteout list 'wp' into the readdir hash table. */static voidinsert_whiteout_into_hash(readdir_hash, wp)	Hash		readdir_hash;	Nse_whiteout	wp;{	char		*file_name;	while (wp != NULL) {		file_name = NSE_STRDUP(wp->name);		if (nse_hash_insert(readdir_hash, file_name, HASH_VALUE)) {			free(file_name);		}		wp = wp->next;	}}intchange_backlist_mtime(pp, name, mtime)	struct pnode	*pp;	char		*name;	long		mtime;{	return modify_backlist(pp, name, change_mtime, (char *) mtime);}/* ARGSUSED */static voidchange_mtime(list, fl, mtime)	Nse_list	list;	Filelist	fl;	long		mtime;{	fl->mtime = mtime;}/* * Change the name of the entry named 'name' to 'newname' in the backlist * of directory 'pp'.  If 'name' was the first directory entry in the * backlist, then insert the old name at the front of the backlist. */intchange_backlist_name(pp, name, newname)	struct pnode	*pp;	char		*name;	char		*newname;{	return modify_backlist(pp, name, change_name, newname);}static voidchange_name(list, fl, newname)	Nse_list	list;	Filelist	fl;	char		*newname;{	Nse_listelem	elem;	Filelist	fl_new;	if (fl->layer == 1 && IS_DIRNAME(fl)) {		elem = nse_list_create_elem(list);		fl_new = (Filelist) nse_listelem_data(elem);		fl_new->fname = NSE_STRDUP(fl->fname);		fl_new->layer = 1;		fl_new->mtime = fl->mtime;		nse_list_insert_head(list, elem);	}	free(fl->fname);	fl->fname = NSE_STRDUP(newname);}/* * Modify the backlist entry for 'name' in the backlist for directory 'pp'. * 'modify_func' is the function to be used to change the entry, and 'arg' * is the argument to 'modify_func'. */static intmodify_backlist(pp, name, modify_func, arg)	struct pnode	*pp;	char		*name;	void		(*modify_func)();	char		*arg;{	Nse_list	backlist;	Filelist	fl;	int		result = 0;	backlist = read_backlist(pp);	if (backlist == NULL) {		return ENOENT;	}	fl = (Filelist) nse_list_search(backlist, backlist_name_eq, name);	if (fl == NULL) {		result = ENOENT;		goto error;	}	modify_func(backlist, fl, arg);	result = write_backlist(pp, backlist);error:	nse_list_destroy(backlist);	return result;}static Nse_listread_backlist(pp)	struct pnode	*pp;{	char		path[MAXPATHLEN];	FILE		*file;	Nse_list	list;	Filelist	fl;	int		count;	int		version;	bool_t		eof = FALSE;	Nse_err		err;	ptoname_or_pn(pp, path);	nse_pathcat(path, NSE_TFS_BACK_FILE);	file = open_tfs_file(path, "r", (Nse_err *) NULL);	if (file == NULL) {		return (NULL);	}	/*	 * Make sure that the version # in the file is correct.	 */	err = nse_fscanf(path, &count, file, NSE_TFS_VERSION_FORMAT, &version);	if (err || count != 1 || version != NSE_TFS_BACKF_VERSION) {		if (err) {			nse_log_err_print(err);		}		fclose(file);		return (NULL);	}	list = filelist_create();	err = read_backlist_entry(file, path, &fl, &eof);	while (!eof) {		(void) nse_list_add_new_data(list, (Nse_opaque) fl);		err = read_backlist_entry(file, path, &fl, &eof);	}	if (err) {		nse_log_err_print(err);	}	fclose(file);	return (list);}static intwrite_backlist(pp, list)	struct pnode	*pp;	Nse_list	list;{	char		path[MAXPATHLEN];	FILE		*file;	Nse_err		err;	ptoname_or_pn(pp, path);	nse_pathcat(path, NSE_TFS_BACK_FILE);	file = open_tfs_file(path, "w", (Nse_err *) NULL);	if (file == NULL) {		return (errno);	}	if ((err = nse_fprintf(path, file, NSE_TFS_VERSION_FORMAT,				NSE_TFS_BACKF_VERSION)) ||	    (err = (Nse_err) nse_list_iterate_or(list, write_backlist_entry,						 file, path)) ||	    (err = nse_fclose(path, file))) {		nse_log_err_print(err);		fclose(file);		(void) unlink(path);		return (err->code);	}	return (0);}#define BACK_FILE_FORMAT	"%s %d %ld\n"static Nse_errread_backlist_entry(file, path, entryp, eofp)	FILE		*file;	char		*path;	Filelist	*entryp;	bool_t		*eofp;{	Filelist	fl;	char		line[MAXPATHLEN];	char		name[MAXPATHLEN];	int		layer;	long		mtime;	int		nitems;	Nse_err		err;	/*	 * Can't use fscanf() because if there is no mtime on the current	 * line and the name of the file on the next line is a number,	 * fscanf() would read the next filename in as the mtime.	 */	err = nse_fgets(path, line, MAXPATHLEN, file, eofp);	if (*eofp) {		return err;	}	nitems = sscanf(line, BACK_FILE_FORMAT, name, &layer, &mtime);	if (nitems < 2) {		*eofp = TRUE;		return NULL;	}	fl = NSE_NEW(Filelist);	fl->fname = NSE_STRDUP(name);	fl->layer = layer;	if (nitems == 3) {		fl->mtime = mtime;	}	*entryp = fl;	return NULL;}static Nse_errwrite_backlist_entry(fl, file, path)	Filelist	fl;	FILE		*file;	char		*path;{	if (fl->mtime != 0) {		return nse_fprintf(path, file, BACK_FILE_FORMAT,				   fl->fname, fl->layer, fl->mtime);	} else {		return nse_fprintf(path, file, "%s %d\n",				   fl->fname, fl->layer);	}}static voidadd_to_backlist(list, name, layer, mtime)	Nse_list	list;	char		*name;	int		layer;	long		mtime;{	Filelist	fl;	fl = (Filelist) nse_list_add_new_elem(list);	fl->fname = NSE_STRDUP(name);	fl->layer = layer;	fl->mtime = mtime;}static Hashinit_dir_hash(){	return (nse_hash_create(HASH_SIZE, NULL,				(Nse_boolfunc) _nse_streq_func,				_nse_hash_string, (Nse_intfunc) NULL, NULL,				(Nse_intfunc) NULL, 7));}static bool_tgood_name(name)	char		*name;{	return (!NSE_STREQ(name, ".") && !NSE_STREQ(name, "..") &&		!is_tfs_special_file(name));}/* * Filelist routines */static bool_tbacklist_is_dir(fl)	Filelist	fl;{	return (IS_DIRNAME(fl));}static bool_tbacklist_name_eq(fl, name)	Filelist	fl;	char		*name;{	return (NSE_STREQ(fl->fname, name));}

⌨️ 快捷键说明

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