win_efile.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 1,417 行 · 第 1/3 页

C
1,417
字号
		    }		    /*		     * Some new error has occurred.  Don't know what it		     * could be, but report this one.		     */		    errno = errno_map(GetLastError());		    CreateDirectory(dst, NULL);		    SetFileAttributes(dst, dstAttr);		    if (errno == EACCES) {			/*			 * Decode the EACCES to a more meaningful error.			 */			goto decode;		    }		}	    } else {	/* (dstAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 */		errno = ENOTDIR;	    }	} else {    /* (srcAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 */	    if (dstAttr & FILE_ATTRIBUTE_DIRECTORY) {		errno = EISDIR;	    } else {		/*		 * Overwrite existing file by:		 * 		 * 1. Rename existing file to temp name.		 * 2. Rename old file to new name.		 * 3. If success, delete temp file.  If failure,		 *    put temp file back to old name.		 */		char tempName[MAX_PATH];		int result, size;		char *rest;				size = GetFullPathName(dst, sizeof(tempName), tempName, &rest);		if ((size == 0) || (size > sizeof(tempName)) || (rest == NULL)) {		    return check_error(-1, errInfo);		}		*rest = '\0';		result = -1;		if (GetTempFileName(tempName, "erlr", 0, tempName) != 0) {		    /*		     * Strictly speaking, need the following DeleteFile and		     * MoveFile to be joined as an atomic operation so no		     * other app comes along in the meantime and creates the		     * same temp file.		     */		     		    DeleteFile(tempName);		    if (MoveFile(dst, tempName) != FALSE) {			if (MoveFile(src, dst) != FALSE) {			    SetFileAttributes(tempName, FILE_ATTRIBUTE_NORMAL);			    DeleteFile(tempName);			    return 1;			} else {			    DeleteFile(dst);			    MoveFile(tempName, dst);			}		    } 		    /*		     * Can't backup dst file or move src file.  Return that		     * error.  Could happen if an open file refers to dst.		     */		    errno = errno_map(GetLastError());		    if (errno == EACCES) {			/*			 * Decode the EACCES to a more meaningful error.			 */			goto decode;		    }		}		return result;	    }	}    }    return check_error(-1, errInfo);}intefile_chdir(errInfo, name)Efile_error* errInfo;		/* Where to return error codes. */char* name;			/* Name of directory to make current. */{    int success = check_error(chdir(name), errInfo);    if (!success && errInfo->posix_errno == EINVAL)	/* POSIXification of errno */	errInfo->posix_errno = ENOENT;    return success;}intefile_getdcwd(errInfo, drive, buffer, size)Efile_error* errInfo;		/* Where to return error codes. */int drive;			/* 0 - current, 1 - A, 2 - B etc. */char* buffer;			/* Where to return the current directory. */size_t size;			/* Size of buffer. */{    if (_getdcwd(drive, buffer, size) == NULL)	return check_error(-1, errInfo);    for ( ; *buffer; buffer++) 	if (*buffer == '\\')	    *buffer = '/';    return 1;}intefile_readdir(errInfo, name, dir_handle, buffer, size)Efile_error* errInfo;		/* Where to return error codes. */char* name;			/* Name of directory to open. */EFILE_DIR_HANDLE* dir_handle;	/* Directory handle of open directory. */char* buffer;			/* Pointer to buffer for one filename. */size_t size;			/* Size of buffer. */{    HANDLE dir;			/* Handle to directory. */    char wildcard[MAX_PATH];	/* Wildcard to search for. */    WIN32_FIND_DATA findData;	/* Data found by FindFirstFile() or FindNext(). */    /*     * First time we must setup everything.     */    if (*dir_handle == NULL) {	int length = strlen(name);	char* s;	if (length+3 >= MAX_PATH) {	    errno = ENAMETOOLONG;	    return check_error(-1, errInfo);	}	strcpy(wildcard, name);	s = wildcard+length-1;	if (*s != '/' && *s != '\\')	    *++s = '\\';	*++s = '*';	*++s = '\0';	DEBUGF(("Reading %s\n", wildcard));	dir = FindFirstFile(wildcard, &findData);	if (dir == INVALID_HANDLE_VALUE)	    return set_error(errInfo);	*dir_handle = (EFILE_DIR_HANDLE) dir;	if (!IS_DOT_OR_DOTDOT(findData.cFileName)) {	    strcpy(buffer, findData.cFileName);	    return 1;	}    }    /*     * Retrieve the name of the next file using the directory handle.     */    dir = (HANDLE) *dir_handle;    for (;;) {	if (FindNextFile(dir, &findData)) {	    if (IS_DOT_OR_DOTDOT(findData.cFileName))		continue;	    strcpy(buffer, findData.cFileName);	    return 1;	}	if (GetLastError() == ERROR_NO_MORE_FILES) {	    FindClose(dir);	    errInfo->posix_errno = errInfo->os_errno = 0;	    return 0;	}	set_error(errInfo);	FindClose(dir);	return 0;    }}intefile_openfile(errInfo, name, flags, pfd, pSize)Efile_error* errInfo;		/* Where to return error codes. */char* name;			/* Name of directory to open. */int flags;			/* Flags to use for opening. */int* pfd;			/* Where to store the file descriptor. */off_t* pSize;			/* Where to store the size of the file. */{    BY_HANDLE_FILE_INFORMATION fileInfo; /* File information from a handle. */    HANDLE fd;			/* Handle to open file. */    DWORD access;		/* Access mode: GENERIC_READ, GENERIC_WRITE. */    DWORD crFlags;    switch (flags & (EFILE_MODE_READ|EFILE_MODE_WRITE)) {    case EFILE_MODE_READ:	access = GENERIC_READ;	crFlags = OPEN_EXISTING;	break;    case EFILE_MODE_WRITE:	access = GENERIC_WRITE;	crFlags = CREATE_ALWAYS;	break;    case EFILE_MODE_READ_WRITE:	access = GENERIC_READ|GENERIC_WRITE;	crFlags = OPEN_ALWAYS;	break;    default:	errno = EINVAL;	check_error(-1, errInfo);	return 0;    }    if (flags & EFILE_MODE_APPEND) {	crFlags = OPEN_ALWAYS;    }    fd = CreateFile(name, access, FILE_SHARE_READ | FILE_SHARE_WRITE,		    NULL, crFlags, FILE_ATTRIBUTE_NORMAL, NULL);    /*     * Check for errors.     */    if (fd == INVALID_HANDLE_VALUE) {	DWORD attr;	set_error(errInfo);	/*	 * If the error is EACESS, the reason could be that we tried to	 * open a directory.  In that case, we'll change the error code	 * to EISDIR.	 */	if (errInfo->posix_errno && 	    (attr = GetFileAttributes(name)) != INVALID_FILE_ATTRIBUTES && 	    (attr & FILE_ATTRIBUTE_DIRECTORY)) {	    errInfo->posix_errno = EISDIR;	}	return 0;    }    /*     * Get and return the length of the open file.     */           if (!GetFileInformationByHandle(fd, &fileInfo))	return set_error(errInfo);    *pfd = (int) fd;    *pSize = fileInfo.nFileSizeLow;    return 1;}int efile_may_openfile(Efile_error* errInfo, char *name) {    DWORD attr;    if ((attr = GetFileAttributes(name)) == INVALID_FILE_ATTRIBUTES) {	return check_error(-1, errInfo);    }    if (attr & FILE_ATTRIBUTE_DIRECTORY) {	errno = EISDIR;	return check_error(-1, errInfo);    }    return 1;#if 0    struct stat statbuf;        if (stat(name, &statbuf)) {	return check_error(-1, errInfo);    }    if (ISDIR(statbuf)) {	errno = EISDIR;	return check_error(-1, errInfo);    }    return 1;#endif}voidefile_closefile(fd)int fd;				/* File descriptor for file to close. */{    CloseHandle((HANDLE) fd);}intefile_fsync(errInfo, fd)Efile_error* errInfo;		/* Where to return error codes. */int fd;				/* File descriptor for file to sync. */{    if (!FlushFileBuffers((HANDLE) fd)) {	return check_error(-1, errInfo);    }    return 1;}intefile_fileinfo(Efile_error* errInfo, Efile_info* pInfo,	       char* orig_name, int info_for_link){    HANDLE findhandle;		/* Handle returned by FindFirstFile(). */    WIN32_FIND_DATA findbuf;	/* Data return by FindFirstFile(). */    char name[_MAX_PATH];    int name_len;    char* path;    char pathbuf[_MAX_PATH];    int drive;			/* Drive for filename (1 = A:, 2 = B: etc). */    /* Don't allow wildcards to be interpreted by system */    if (strpbrk(orig_name, "?*")) {    enoent:	errInfo->posix_errno = ENOENT;	errInfo->os_errno = ERROR_FILE_NOT_FOUND;        return 0;    }    /*     * Move the name to a buffer and make sure to remove a trailing     * slash, because it causes FindFirstFile() to fail on Win95.     */    if ((name_len = strlen(orig_name)) >= _MAX_PATH) {	goto enoent;    } else {	strcpy(name, orig_name);	if (name_len > 2 && ISSLASH(name[name_len-1]) &&	    name[name_len-2] != ':') {	    name[name_len-1] = '\0';	}    }        /* Try to get disk from name.  If none, get current disk.  */    if (name[1] != ':') {        drive = 0;        if (GetCurrentDirectory(sizeof(pathbuf), pathbuf) &&	    pathbuf[1] == ':') {	    drive = tolower(pathbuf[0]) - 'a' + 1;	}    } else if (*name && name[2] == '\0') {	/*	 * X: and nothing more is an error.	 */	errInfo->posix_errno = ENOENT;	errInfo->os_errno = ERROR_FILE_NOT_FOUND;	return 0;    } else        drive = tolower(*name) - 'a' + 1;    findhandle = FindFirstFile(name, &findbuf);    if (findhandle == INVALID_HANDLE_VALUE) {        if (!(strpbrk(name, "./\\") &&	      (path = _fullpath(pathbuf, name, _MAX_PATH)) &&	      /* root dir. ('C:\') or UNC root dir. ('\\server\share\') */	      ((strlen(path) == 3) || IsRootUNCName(path)) &&	      (GetDriveType(path) > 1)   ) ) {	    errInfo->posix_errno = ENOENT;	    errInfo->os_errno = ERROR_FILE_NOT_FOUND;	    return 0;	}        /*         * Root directories (such as C:\ or \\server\share\ are fabricated.         */	        findbuf.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;        findbuf.nFileSizeHigh = 0;        findbuf.nFileSizeLow = 0;        findbuf.cFileName[0] = '\0';	pInfo->modifyTime.year = 1980;	pInfo->modifyTime.month = 1;	pInfo->modifyTime.day = 1;	pInfo->modifyTime.hour = 0;	pInfo->modifyTime.minute = 0;	pInfo->modifyTime.second = 0;	pInfo->accessTime = pInfo->modifyTime;    } else {	SYSTEMTIME SystemTime;        FILETIME LocalFTime;#define GET_TIME(dst, src) \if (!FileTimeToLocalFileTime(&findbuf.src, &LocalFTime) || \    !FileTimeToSystemTime(&LocalFTime, &SystemTime)) { \    return set_error(errInfo); \} \(dst).year = SystemTime.wYear; \(dst).month = SystemTime.wMonth; \(dst).day = SystemTime.wDay; \(dst).hour = SystemTime.wHour; \(dst).minute = SystemTime.wMinute; \(dst).second = SystemTime.wSecond;        GET_TIME(pInfo->modifyTime, ftLastWriteTime);        if (findbuf.ftLastAccessTime.dwLowDateTime == 0 &&	    findbuf.ftLastAccessTime.dwHighDateTime == 0) {	    pInfo->accessTime = pInfo->modifyTime;	} else {	    GET_TIME(pInfo->accessTime, ftLastAccessTime);	}        if (findbuf.ftCreationTime.dwLowDateTime == 0 &&	    findbuf.ftCreationTime.dwHighDateTime == 0) {	    pInfo->cTime = pInfo->modifyTime;	} else {	    GET_TIME(pInfo->cTime, ftCreationTime);	}#undef GET_TIME        FindClose(findhandle);    }    pInfo->size_low = findbuf.nFileSizeLow;    pInfo->size_high = findbuf.nFileSizeHigh;	    if (findbuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)	pInfo->type = FT_DIRECTORY;    else	pInfo->type = FT_REGULAR;    if (findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY)	pInfo->access = FA_READ;    else	pInfo->access = FA_READ|FA_WRITE;    pInfo->mode = dos_to_posix_mode(findbuf.dwFileAttributes, name);    pInfo->links = 1;    pInfo->major_device = drive;    pInfo->minor_device = 0;    pInfo->inode = 0;    pInfo->uid = 0;    pInfo->gid = 0;        return 1;}intefile_write_info(errInfo, pInfo, name)Efile_error* errInfo;Efile_info* pInfo;char* name;{    SYSTEMTIME timebuf;    FILETIME LocalFileTime;    FILETIME ModifyFileTime;    FILETIME AccessFileTime;    FILETIME CreationFileTime;    HANDLE fd;    FILETIME* mtime = NULL;    FILETIME* atime = NULL;    FILETIME* ctime = NULL;    DWORD attr;    DWORD tempAttr;    BOOL modifyTime = FALSE;    /*     * Get the attributes for the file.     */    tempAttr = attr = GetFileAttributes((LPTSTR)name);    if (attr == 0xffffffff) {	return set_error(errInfo);    }    if (pInfo->mode != -1) {	if (pInfo->mode & _S_IWRITE) {	    /* clear read only bit */	    attr &= ~FILE_ATTRIBUTE_READONLY;	} else {	    /* set read only bit */

⌨️ 快捷键说明

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