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

📄 simple_restore.c

📁 网络数据管理协议的开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/*                               -*- Mode: C -*-  * simple_restore.c *  * Description     : Simple restore functions. *  * Copyright (c) 1996,1997 PDC, Network Appliance. All Rights Reserved. * * $Id: simple_restore.c,v 1.9 1998/05/26 03:52:23 tim Exp $ */#if !defined(lint) && !defined(SABER)static char rcsId[] __attribute__ ((unused)) = "@(#) $Id: simple_restore.c,v 1.9 1998/05/26 03:52:23 tim Exp $";#endif#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/mman.h>#include <string.h>#include <libgen.h>#include "simple_private.h"typedef struct RestoreInfo{	SimpleParams	*params;	bool_t			setUidGid;	bool_t			direct;	char			destDir[MAXPATHLEN+1];	u_long			nFiles;} RestoreInfo;static intregularRestore(RestoreInfo*	info);static intdirectRestore(RestoreInfo*	info);static intcheckFile(RestoreInfo*	info,		  char*			name);static intrestoreFile(RestoreInfo*	info,			char*			name,			struct stat*	fileStat);static intdiscardFile(RestoreInfo*	info,			char*			name,			struct stat*	fileStat);/* * simpleRestore *   Restores data dumped by the simple dump module. *   Sends a file recovered request for every file in the file list. * * Parameters: *   params (input) - restore parameters. * * Returns: *   0 - success. *   error code. */intsimpleRestore(SimpleParams*	params){	RestoreInfo			info;	u_long				nameLen;	int					err;	NdmpdModuleParams*	modParams = params->modParams;	ndmp_name*			nameEnt;	char*				directStr;		info.params = params;		/*	 * Validate restore name list and construct the destination path.	 * The following functionality is *not* supported:	 *   - restore file renaming. Restoring a file with a name different	 *     from the name of the file on the restore tape.	 *   - multiple restore destination root directories. 	 *	 * Therefore, for each recover file name entry:	 *   - the last X characters of dest must match name where X is the	 *     length of name.	 *   - the first L-X characters of each dest must match where L is	 *     the length of dest. The destination path of all	 *     entries must be the same.	 */	for (info.nFiles = 0; ; info.nFiles++)	{		u_long	destlen;				nameEnt = (*modParams->getNameFunc)(modParams->daemonCookie,											info.nFiles);		if (nameEnt == 0)			break;				destlen = strlen(nameEnt->destination_dir);				if (strlen(nameEnt->original_path) > destlen)		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,								  "Restore: ERROR: name entry %ld: name is longer than dest.\n",								  info.nFiles);			return(EINVAL);		}		destlen -= strlen(nameEnt->original_path);				if (destlen > MAXPATHLEN)		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,								  "Restore: ERROR: name entry %ld: dest longer than MAXPATHLEN.\n",								  info.nFiles);			return(EINVAL);		}				/*		 * Source and destination name must be the same		 * relative to the destination directory.		 */		if (strcmp(nameEnt->original_path, &nameEnt->destination_dir[destlen]) != 0)		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,								  "Restore: ERROR: name entry %ld: name/dest mismatch relative to destination directory \n",								  info.nFiles);			return(EINVAL);		}		if (info.nFiles == 0)		{			strncpy(info.destDir, nameEnt->destination_dir, destlen);			info.destDir[destlen] = '\0';		}		else		{			/*			 * All files must have the same destination directory.			 */			if (strncmp(info.destDir, nameEnt->destination_dir,						strlen(info.destDir)) != 0)			{				(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,									  "Restore: ERROR: name entry %ld: dest does not destination directory \n",									  info.nFiles);				return(EINVAL);			}		}	}	if (info.nFiles == 0)	{		(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,							  "Restore: ERROR: empty name list.\n");		return(EINVAL);	}		/*	 * Adjust destDir so that it ends with a /	 */	nameLen = strlen(info.destDir);	if (nameLen == 0)		strcpy(info.destDir, "/");	else if (info.destDir[nameLen-1] != '/')		strcat(info.destDir, "/");	if (geteuid() == 0)		info.setUidGid = TRUE;	else		info.setUidGid = FALSE;		directStr = (*modParams->getEnvFunc)(modParams->daemonCookie,										 "DIRECT");	if (directStr)	{		if (directStr[0] == 't' || directStr[0] == 'T' ||			directStr[0] == 'y' || directStr[0] == 'Y')			info.direct = TRUE;		else			info.direct = FALSE;	}	else		info.direct = FALSE;	if (info.direct == TRUE)		err = directRestore(&info);	else		err = regularRestore(&info);		return(err);}/* * regularRestore *   Restores files by reading each file entry on tape, checking if the file *   matches an entry in the name list, and restoring the file to disk if *   if it matches. * * Paramters: *   info (input) - restore info. * * Returns: *  error code. */static intregularRestore(RestoreInfo*	info){	struct stat			fileStat;	struct stat			zeroFileStat;	char				*recoveredList;	NdmpdModuleParams	*modParams = info->params->modParams;	int					err;	u_long				nameLen;	char				name[MAXPATHLEN];		memset((void*)&zeroFileStat, 0, sizeof(zeroFileStat));	recoveredList = (char*)malloc(info->nFiles);	if (recoveredList == 0)	{		(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,							  "Restore: ERROR: malloc: %s\n",							  strerror(errno));		return(ENOMEM);	}		/* Zero the list to mark no files as having been recovered yet. */	memset((void*)recoveredList, 0, info->nFiles);		for (;;)	{		int		match;		/*		 * Read the file status data for the next file.		 */		if ((*modParams->readFunc)(modParams->daemonCookie,								   (char*)&fileStat,								   sizeof(fileStat)) < 0)		{			err = EIO;			break;		}		modParams->stats->bytesProcessed += sizeof(fileStat);				/*		 * Check for end of dump marked by a zeroed file status record.		 */		if (memcmp((void*)&fileStat, (void*)&zeroFileStat,				   sizeof(fileStat)) == 0)		{			err = 0;			break;		}				/*		 * Read the length of the file name.		 */		if ((*modParams->readFunc)(modParams->daemonCookie,								   (char*)&nameLen,								   sizeof(nameLen)) < 0)		{			err = EIO;			break;		}		modParams->stats->bytesProcessed += sizeof(nameLen);		if (nameLen > sizeof(name))		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,							   "Restore: ERROR: read invalid file name length.\n");			err = EIO;			break;		}				/*		 * Read the file name.		 */		if ((*modParams->readFunc)(modParams->daemonCookie,								   (char*)name,								   nameLen) < 0)		{			err = EIO;			break;		}		modParams->stats->bytesProcessed += nameLen;		name[nameLen] = '\0';				/*		 * Check if the file should be restored.		 */		if ((match = checkFile(info, name)) >= -1)		{			err = restoreFile(info, name, &fileStat);			if (err < 0)			{				err = EIO;				break;			}			/*			 * Only notify the NDMP client that a file recovery succeeded			 * or failed if the file exactly matches a file from the			 * restore list.			 */			if (match >= 0)			{				recoveredList[match] = 1;				(*modParams->fileRecoveredFunc)(modParams->daemonCookie,												name,												(err == 0 ? EPERM : 0));			}		}		else		{			if (discardFile(info, name, &fileStat) < 0)			{				err = EIO;				break;			}		}		/*		 * Check if the restore has been aborted		 * or the NDMP connection broken.		 */		(*modParams->dispatchFunc)(modParams->daemonCookie, FALSE);		if (info->params->abortFlag == TRUE)		{			err = EINTR;			break;		}	}		/*	 * Notify client of all files in recover list that were not found.	 */	if (err == 0)	{		u_long	i;		for (i = 0; i < info->nFiles; i++)		{			ndmp_name*	nameEnt;			nameEnt = (*modParams->getNameFunc)(modParams->daemonCookie,												i);			if (recoveredList[i] == 0)				(*modParams->fileRecoveredFunc)(modParams->daemonCookie,												nameEnt->original_path,												ENOENT);		}	}		free(recoveredList);	return(err);}/* * directRestore *   Restores files by seeking the tape to the offset of each file to be *   restored and restoring the file. * * Paramters: *   info (input) - restore info. * * Returns: *  error code. */static intdirectRestore(RestoreInfo*	info){	struct stat			fileStat;	struct stat			zeroFileStat;	ndmp_name			*nameEnt;	NdmpdModuleParams	*modParams = info->params->modParams;	int					err;	u_long				nameLen;	char				name[MAXPATHLEN];	char*				n1;	char*				n2;	u_long				i;		memset((void*)&zeroFileStat, 0, sizeof(zeroFileStat));	for (i = 0; i < info->nFiles; i++)	{		nameEnt = (*modParams->getNameFunc)(modParams->daemonCookie, i);		if (nameEnt == 0)		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,								  "Restore: ERROR: name list error.\n");			return(EINVAL);		}				if ((*modParams->seekFunc)(modParams->daemonCookie,								   ((u_longlong_t)nameEnt->fh_info.high << 32) +								   nameEnt->fh_info.low,								   (u_longlong_t)sizeof(fileStat) +								   sizeof(nameLen)) < 0)		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,							   "Restore: ERROR: seeking.\n");			return(EIO);		}				/*		 * Read the file status data for the file.		 */		if ((*modParams->readFunc)(modParams->daemonCookie,								   (char*)&fileStat,								   sizeof(fileStat)) < 0)		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,							   "Restore: ERROR: reading file status.\n");			return(EIO);		}		modParams->stats->bytesProcessed += sizeof(fileStat);				/*		 * Check for end of dump marked by a zeroed file status record.		 */		if (memcmp((void*)&fileStat, (void*)&zeroFileStat,				   sizeof(fileStat)) == 0)		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,							   "Restore: ERROR: unexpected EOF.\n");			return(EIO);		}				/*		 * Read the length of the file name.		 */		if ((*modParams->readFunc)(modParams->daemonCookie,								   (char*)&nameLen,								   sizeof(nameLen)) < 0)		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,							   "Restore: ERROR: reading file name length.\n");			return(EIO);		}		modParams->stats->bytesProcessed += sizeof(nameLen);		if (nameLen > sizeof(name))		{			(*modParams->logFunc)(modParams->daemonCookie, NDMP_LOG_NORMAL, 0,							   "Restore: ERROR: read invalid file name length.\n");			return(EIO);		}				/*		 * Read the file name.		 */		if ((*modParams->readFunc)(modParams->daemonCookie,								   (char*)name,								   nameLen) < 0)		{			return (EIO);		}		modParams->stats->bytesProcessed += nameLen;		name[nameLen] = '\0';				/*		 * Verify this is the correct file.		 * Need to normalize the file names by removing any leading ./ or / component		 * and also need to handle the . directory.		 */		n1 = name;		n2 = nameEnt->original_path;

⌨️ 快捷键说明

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