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

📄 simple_restore.c

📁 网络数据管理协议的开发
💻 C
📖 第 1 页 / 共 2 页
字号:
		if (n1[0] == '.' && n1[1] == '/')			n1 += 2;		else if (n1[0] == '/' ||				 (n1[0] == '.' && n1[1] == '\0'))			n1++;		if (n2[0] == '.' && n2[1] == '/')			n2 += 2;		else if (n2[0] == '/' ||				 (n2[0] == '.' && n2[1] == '\0'))			n2++;				if (strcmp(n1, n2) != 0)		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,							   "Restore: ERROR: expected file: %s; read: %s.\n",								  nameEnt->original_path, name);			return(EIO);		}				err = restoreFile(info, name, &fileStat);		if (err < 0)		{			return(EIO);		}		/*		 * Notify the NDMP client that a file recovery succeeded or		 * failed.		 */		(*modParams->fileRecoveredFunc)(modParams->daemonCookie,										name,										(err == 0 ? EPERM : 0));		/*		 * Check if the restore has been aborted		 * or the NDMP connection broken.		 */		(*modParams->dispatchFunc)(modParams->daemonCookie, FALSE);		if (info->params->abortFlag == TRUE)		{			return(EINTR);		}	}	return(0);}/* * checkFile *   Determine if the specified file name should be restored by *   comparing the name to each name in the restore list. *   Look for exact match as well as if the name is a parent directory *   to a file in the restore list or is contained in a directory *   specified in the restore list. * *   Before comparing names, names are normalized by removing any *   leading / or ./. A name of .\0 is normalized to \0. *   A resulting normalized name of \0 implies the backup root *   directory of the dump. * * Parameters: *   info (input) - restore info. *   name (input) - file name to check. * * Returns: *  -2 - no match. *  -1 - name is a parent directory of a file in the list or *       name is contained in a directory from the list. *   otherwise - index into list of the exact matching name. */static intcheckFile(RestoreInfo*	info,		  char*			name){	char*				ckname;	u_long				cknamelen;	u_long				namelen;	u_long				i;	int					match = -2;	NdmpdModuleParams*	modParams = info->params->modParams;		/*	 * Remove leading ./	 * Force . (backup root directory) to match everything.	 */	if (name[0] == '.' && name[1] == '/')		name += 2;	else if (name[0] == '.' && name[1] == '\0')		name++;	/*	 * Always restore the backup root directory. 	 * Still need to check for an exact match.	 */	if (name[0] == '\0')		match = -1;		/*	 * Check against each name in the restore list until a	 * match is found or until the end of the list is encountered.	 */	for (i = 0; ; i++)	{		ndmp_name*	nameEnt;		nameEnt = (*modParams->getNameFunc)(modParams->daemonCookie,											i);		if (nameEnt == 0)			break;				ckname    = nameEnt->original_path;		/* Remove leading ./ or / */		if (ckname[0] == '.' && ckname[1] == '/')			ckname += 2;		else if (ckname[0] == '/' ||				 (ckname[0] == '.' && ckname[1] == '\0'))			ckname++;				/* Root directory matches all names. */		if (ckname[0] == '\0')			match = -1;				cknamelen = strlen(ckname);		namelen   = strlen(name);				if (namelen == cknamelen)		{			if (strcmp(name, ckname) == 0)				return(i);			continue;		}				if (namelen < cknamelen)		{			/*			 * Its only a match if name is a parent directory of ckname.			 */			if (ckname[namelen] != '/')				continue;						if (strncmp(name, ckname, namelen) != 0)				continue;			/* Found a match but keep looking for an exact match. */			match = -1;			continue;		}				/*		 * Its only a match now if ckname is a parent directory to name.		 */		if (name[cknamelen] != '/')			continue;					if (strncmp(name, ckname, cknamelen) != 0)			continue;		/* Found a match but keep looking for an exact match. */		match = -1;	}	return(match);}/* * restoreFile *   Restores the specified file. * * Parameters: *   info (input)     - restore info. *   name (input)     - name of file being restored. *   fileStat (input) - file stat data. * * Returns: *  -1 - error reading file dump data. *   0 - error creating file or setting attributes. *   1 - file successfully restored. */static intrestoreFile(RestoreInfo*	info,			char*			name,			struct stat*	fileStat){	char				path[MAXPATHLEN+1];	NdmpdModuleParams*	modParams = info->params->modParams;	if (strlen(name) + strlen(info->destDir) > MAXPATHLEN)	{		(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,							  "Restore: ERROR: MAXPATHLEN exceeded for: %s%s.\n",							  info->destDir, name);		return(discardFile(info, name, fileStat));	}			/*	 * Remove leading ./	 * This is not really necessary but is done so that the file names	 * in error messages don't contain embedded /./	 */	if (name[0] == '.' && name[1] == '/')		name += 2;	else if (name[0] == '.')		name++;	strcpy(path, info->destDir);	strcat(path, name);		/*	 * Don't overwrite files.	 * This is enforced mostly to prevent buggy code from	 * destroying the filesystem.	 * It also simplifies the code since since existing files	 * don't have to be dealt with. This is especially a problem if	 * the file exists and is of a different type than the file being restored.	 */	if (access(path, F_OK) == 0)	{		(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,							  "Restore: ERROR: file exists: %s.\n",							  path);		return(discardFile(info, path, fileStat));	}		/*	 * For direct access restores, the parent directories only get	 * created if explictly specified in the name list so create	 * them here if they do not already exist.	 */	if (info->direct && (fileStat->st_mode & S_IFMT) != S_IFDIR)	{		char*	p = strrchr(path, '/');		if (p != 0 && p != path)		{			*p = '\0';			if (access(path, F_OK) != 0)			{				if (mkdirp(path, fileStat->st_mode&S_IAMB) < 0)				{					(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,										  "Restore: ERROR: creating directory: %s: %s.\n",										  path, strerror(errno));					*p = '/';					return(0);				}			}						*p = '/';		}	}		switch (fileStat->st_mode & S_IFMT)	{		case S_IFDIR:		{			if (mkdirp(path, fileStat->st_mode&S_IAMB) < 0)			{				(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,									  "Restore: ERROR: creating directory: %s: %s.\n",									  path, strerror(errno));				return(0);			}			break;		}				case S_IFIFO:		case S_IFBLK:		case S_IFCHR:		{			if (mknod(path,					  fileStat->st_mode,					  fileStat->st_dev) < 0)			{				(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,									  "Restore: ERROR: creating file: %s: %s.\n",									  path, strerror(errno));				return(0);			}			break;		}		case S_IFREG:		{			int		fd;			caddr_t	addr;			if ((fd = open(path, O_RDWR|O_CREAT,						   fileStat->st_mode&S_IAMB)) < 0)			{				(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,									  "Restore: ERROR: creating file: %s: %s.\n",									  path, strerror(errno));				return(discardFile(info, path, fileStat));			}			/* Set the file length so mmap works. */			if (ftruncate(fd, fileStat->st_size) < 0)			{				(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,									  "Restore: ERROR: setting file size: %s: %s.\n",									  name, strerror(errno));				(void)close(fd);				return(discardFile(info, path, fileStat));			}						if (fileStat->st_size == 0)			{				close(fd);				break;			}						/* Map in the file. */			addr = mmap(0, fileStat->st_size, PROT_WRITE, MAP_SHARED,						fd, 0);			if (addr == MAP_FAILED)			{				(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,									  "Restore: ERROR: mapping file: %s: %s.\n",									  path, strerror(errno));				(void)close(fd);				return(discardFile(info, path, fileStat));			}			/* Read the file data into the file via the mapped address. */			if ((*modParams->readFunc)(modParams->daemonCookie,									   addr, fileStat->st_size) < 0)			{				(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,									  "Restore: ERROR: reading file data: %s: %s.\n",								   path, strerror(errno));				(void)munmap(addr, fileStat->st_size);				(void)close(fd);				return(-1);			}						modParams->stats->bytesProcessed += fileStat->st_size;			(void)munmap(addr, fileStat->st_size);			(void)close(fd);			break;		}				case S_IFLNK:		{			char	linkName[MAXPATHLEN];						/*			 * Read the link name.			 */			if ((*modParams->readFunc)(modParams->daemonCookie,									   (char*)linkName,									   fileStat->st_size) < 0)			{				(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,									  "Restore: ERROR: reading file data: %s: %s.\n",									  path, strerror(errno));				return(-1);			}			modParams->stats->bytesProcessed += fileStat->st_size;			linkName[fileStat->st_size] = '\0';						if (symlink(linkName, path) < 0)			{				(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,									  "Restore: ERROR: creating symbolic link: %s: %s.\n",									  path, strerror(errno));				return(0);			}						break;		}				default:		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,								  "Restore: ERROR: unsupported file type(0%o): %s.\n",								  fileStat->st_mode&S_IFMT, path);			return(0);		}	}	if (info->setUidGid == TRUE)	{		/*		 * Set file owner and group.		 */		if (chown(path, fileStat->st_uid, fileStat->st_gid) < 0)		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,									 "Restore: ERROR: setting uid/gid: %s.\n",									 path);			return(0);		}	}		return(1);}/* * discardFile *   Read and discard file data. * * Parameters: *   info (input)     - restore info. *   name (input)     - file name. *   size (input)     - file size. * * Returns: *   -1 - error reading file data. *    0 - success. */static intdiscardFile(RestoreInfo*	info,			char*			name,			struct stat*	fileStat){	int		fd;	caddr_t	addr;	NdmpdModuleParams*	modParams = (NdmpdModuleParams*) info->params->modParams;	#if 0	/*	 * No need to discard if direct access restore since seeking	 * is done before reading each file.	 */	if (info->direct == TRUE)		return(0);#endif		/*	 * Only regular files and symbolic link files have	 * data that needs to be discarded.	 */	if ((fileStat->st_mode & S_IFMT) != S_IFREG &&		(fileStat->st_mode & S_IFMT) != S_IFLNK)		return(0);		if (fileStat->st_size == 0)		return(0);		if ((fd = open("/dev/zero", O_RDWR)) < 0)	{		(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,								 "Restore: ERROR: opening /dev/zero: %s.\n",								 strerror(errno));		return(-1);	}	addr = mmap(0, fileStat->st_size, PROT_WRITE, MAP_PRIVATE, fd, 0);	if (addr == MAP_FAILED)	{		(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,								 "Restore: ERROR: mapping /dev/zero: %s.\n",								 strerror(errno));		(void)close(fd);		return(-1);	}	/* Read the file data. */	if ((*modParams->readFunc)(modParams->daemonCookie,								  addr, fileStat->st_size) < 0)	{		(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,								 "Restore: ERROR: reading file data: %s: %s.\n",								 name, strerror(errno));		(void)munmap(addr, fileStat->st_size);		(void)close(fd);		return(-1);	}				modParams->stats->bytesProcessed += fileStat->st_size;	(void)munmap(addr, fileStat->st_size);	(void)close(fd);	return(0);}

⌨️ 快捷键说明

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