win_efile.c

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

C
1,417
字号
	    attr |= FILE_ATTRIBUTE_READONLY;	}    }    /*     * Construct all file times.     */#define MKTIME(tb, ts, ptr) \    timebuf.wYear = ts.year; \    timebuf.wMonth = ts.month; \    timebuf.wDay = ts.day; \    timebuf.wHour = ts.hour; \    timebuf.wMinute = ts.minute; \    timebuf.wSecond = ts.second; \    timebuf.wMilliseconds = 0; \    if (ts.year != -1) { \      modifyTime = TRUE; \      ptr = &tb; \      if (!SystemTimeToFileTime(&timebuf, &LocalFileTime ) || \	!LocalFileTimeToFileTime(&LocalFileTime, &tb)) { \        errno = EINVAL; \	return check_error(-1, errInfo); \     } \    }    MKTIME(ModifyFileTime, pInfo->accessTime, mtime);    MKTIME(AccessFileTime, pInfo->modifyTime, atime);    MKTIME(CreationFileTime, pInfo->cTime, ctime);#undef MKTIME    /*     * If necessary, set the file times.     */    if (modifyTime) {	/*	 * If the has read only access, we must temporarily turn on	 * write access (this is necessary for native filesystems,	 * but not for NFS filesystems).	 */	if (tempAttr & FILE_ATTRIBUTE_READONLY) {	    tempAttr &= ~FILE_ATTRIBUTE_READONLY;	    if (!SetFileAttributes((LPTSTR) name, tempAttr)) {		return set_error(errInfo);	    }	}	fd = CreateFile(name, GENERIC_READ|GENERIC_WRITE,			FILE_SHARE_READ | FILE_SHARE_WRITE,			NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);	if (fd != INVALID_HANDLE_VALUE) {	    BOOL result = SetFileTime(fd, ctime, atime, mtime);	    if (!result) {		return set_error(errInfo);	    }	    CloseHandle(fd);	}    }    /*     * If the file doesn't have the correct attributes, set them now.     * (It could have been done before setting the file times, above).     */    if (tempAttr != attr) {	if (!SetFileAttributes((LPTSTR) name, attr)) {	    return set_error(errInfo);	}    }    return 1;}intefile_pwrite(errInfo, fd, buf, count, offset)Efile_error* errInfo;		/* Where to return error codes. */int fd;				/* File descriptor to write to. */char* buf;			/* Buffer to write. */size_t count;			/* Number of bytes to write. */off_t offset;			/* where to write it */{    int res, location;    if ((res = efile_seek(errInfo, fd, offset, 			  EFILE_SEEK_SET, &location)))	return efile_write(errInfo, EFILE_MODE_WRITE, fd, buf, count);    else	return res;}/* position and read/write as a single atomic op */intefile_pread(errInfo, fd, offset, buf, count, pBytesRead)Efile_error* errInfo;		/* Where to return error codes. */int fd;				/* File descriptor to read from. */off_t offset;			/* Offset in bytes from BOF. */char* buf;			/* Buffer to read into. */size_t count;			/* Number of bytes to read. */size_t* pBytesRead;		/* Where to return number of bytes read. */{    int res, location;    if ((res = efile_seek(errInfo, fd, offset, EFILE_SEEK_SET, 			  &location)))	return efile_read(errInfo, EFILE_MODE_READ, fd, buf, count, pBytesRead);    else	return res;}intefile_write(errInfo, flags, fd, buf, count)Efile_error* errInfo;		/* Where to return error codes. */int flags;			/* Flags given when file was opened. */int fd;				/* File descriptor to write to. */char* buf;			/* Buffer to write. */size_t count;			/* Number of bytes to write. */{    DWORD written;		/* Bytes written in last operation. */    if (flags & EFILE_MODE_APPEND) {	(void) SetFilePointer((HANDLE) fd, 0, NULL, FILE_END);    }    while (count > 0) {	if (!WriteFile((HANDLE) fd, buf, count, &written, NULL))	    return set_error(errInfo);	buf += written;	count -= written;    }    return 1;}intefile_writev(Efile_error* errInfo,   /* Where to return error codes */	     int flags,              /* Flags given when file was				      * opened */	     int fd,                 /* File descriptor to write to */	     SysIOVec* iov,          /* Vector of buffer structs.				      * The structs are unchanged 				      * after the call */	     int iovcnt,             /* Number of structs in vector */	     size_t size)            /* Number of bytes to write */{    int cnt;                         /* Buffers so far written */    ASSERT(iovcnt >= 0);        if (flags & EFILE_MODE_APPEND) {	(void) SetFilePointer((HANDLE) fd, 0, NULL, FILE_END);    }    for (cnt = 0; cnt < iovcnt; cnt++) {	if (iov[cnt].iov_base && iov[cnt].iov_len > 0) {	    /* Non-empty buffer */	    int p;                   /* Position in buffer */	    int w = iov[cnt].iov_len;/* Bytes written in this call */	    for (p = 0; p < iov[cnt].iov_len; p += w) {		if (!WriteFile((HANDLE) fd, 			       iov[cnt].iov_base + p, 			       iov[cnt].iov_len - p, 			       &w, 			       NULL))		    return set_error(errInfo);	    }	}    }	    return 1;}intefile_read(errInfo, flags, fd, buf, count, pBytesRead)Efile_error* errInfo;		/* Where to return error codes. */int flags;			/* Flags given when file was opened. */int fd;				/* File descriptor to read from. */char* buf;			/* Buffer to read into. */size_t count;			/* Number of bytes to read. */size_t* pBytesRead;		/* Where to return number of bytes read. */{    if (!ReadFile((HANDLE) fd, buf, count, (DWORD *) pBytesRead, NULL))	return set_error(errInfo);    return 1;}intefile_seek(errInfo, fd, offset, origin, new_location)Efile_error* errInfo;		/* Where to return error codes. */int fd;				/* File descriptor to do the seek on. */off_t offset;			/* Offset in bytes from the given origin. */int origin;			/* Origin of seek (SEEK_SET, SEEK_CUR,				 * SEEK_END).				 */off_t* new_location;		/* Resulting new location in file. */{    DWORD result;    switch (origin) {    case EFILE_SEEK_SET: origin = FILE_BEGIN; break;    case EFILE_SEEK_CUR: origin = FILE_CURRENT; break;    case EFILE_SEEK_END: origin = FILE_END; break;    default:	errno = EINVAL;	check_error(-1, errInfo);	break;    }    result = SetFilePointer((HANDLE) fd, offset, NULL, origin);    if (result == (DWORD) -1)	return set_error(errInfo);    DEBUGF(("efile_seek(offset=%d, origin+%d) -> %d\n", offset, origin, result));    *new_location = (unsigned) result;    return 1;}intefile_truncate_file(errInfo, fd, flags)Efile_error* errInfo;		/* Where to return error codes. */int *fd;				/* File descriptor for file to truncate. */int flags;{    if (!SetEndOfFile((HANDLE) (*fd)))	return set_error(errInfo);    return 1;}/* * IsRootUNCName - returns TRUE if the argument is a UNC name specifying *      a root share.  That is, if it is of the form \\server\share\. *      This routine will also return true if the argument is of the *      form \\server\share (no trailing slash) but Win32 currently *      does not like that form. * *      Forward slashes ('/') may be used instead of backslashes ('\'). */static intIsRootUNCName(const char* path){    /*     * If a root UNC name, path will start with 2 (but not 3) slashes     */    if ((strlen(path) >= 5) /* minimum string is "//x/y" */	&& ISSLASH(path[0]) && ISSLASH(path[1]))    {        const char * p = path + 2 ;        /*         * find the slash between the server name and share name         */        while ( * ++ p )            if ( ISSLASH(*p) )                break ;        if ( *p && p[1] )        {            /*             * is there a further slash?             */            while ( * ++ p )                if ( ISSLASH(*p) )                    break ;            /*             * just final slash (or no final slash)             */            if ( !*p || !p[1])                return 1;        }    }    return 0 ;}/* * Extracts the root part of an absolute filename (by modifying the string * pointed to by the name argument).  The name can start * with either a driver letter (for example, C:\), or a UNC name * (for example, \\guinness\bjorn). * * If the name is invalid, the buffer will be modified to point to * an empty string. * * Returns: 1 if the name consists of just the root part, 0 if * 	    the name was longer. */static intextract_root(char* name){    int len = strlen(name);    if (isalpha(name[0]) && name[1] == ':' && ISSLASH(name[2])) {	int c = name[3];	name[3] = '\0';	return c == '\0';    } else if (len < 5 || !ISSLASH(name[0]) || !ISSLASH(name[1])) {	goto error;    } else {			/* Try to find the end of the UNC name. */	char* p;	int c;        /*         * Find the slash between the server name and share name.         */	for (p = name + 2; *p; p++)            if (ISSLASH(*p))                break;	if (*p == '\0')	    goto error;	/*	 * Find the slash after the share name.	 */	for (p++; *p; p++)            if (ISSLASH(*p))                break;	c = *p;	*p = '\0';	return c == '\0' || p[1] == '\0';    } error:    *name = '\0';    return 1;}static unsigned shortdos_to_posix_mode(int attr, const char *name){    register unsigned short uxmode;    unsigned dosmode;    register const char *p;    dosmode = attr & 0xff;    if ((p = name)[1] == ':')	p += 2;    /* check to see if this is a directory - note we must make a special     * check for the root, which DOS thinks is not a directory     */    uxmode = (unsigned short)	(((ISSLASH(*p) && !p[1]) || (dosmode & FILE_ATTRIBUTE_DIRECTORY) ||	       *p == '\0') ? _S_IFDIR|_S_IEXEC : _S_IFREG);    /* If attribute byte does not have read-only bit, it is read-write */    uxmode |= (dosmode & FILE_ATTRIBUTE_READONLY) ?	_S_IREAD : (_S_IREAD|_S_IWRITE);    /* see if file appears to be executable - check extension of name */    if (p = strrchr(name, '.')) {        if (!stricmp(p, ".exe") ||	    !stricmp(p, ".cmd") ||	    !stricmp(p, ".bat") ||	    !stricmp(p, ".com"))            uxmode |= _S_IEXEC;    }    /* propagate user read/write/execute bits to group/other fields */    uxmode |= (uxmode & 0700) >> 3;    uxmode |= (uxmode & 0700) >> 6;    return uxmode;}intefile_readlink(Efile_error* errInfo, char* name, char* buffer, size_t size){    errno = ENOTSUP;    return check_error(-1, errInfo);}intefile_altname(Efile_error* errInfo, char* orig_name, char* buffer, size_t size){    WIN32_FIND_DATA wfd;    HANDLE fh;    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.	 */	goto enoent;    } else {        drive = tolower(*name) - 'a' + 1;    }    fh = FindFirstFile(name,&wfd);    if (fh == 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)   ) ) {	    errno = errno_map(GetLastError());	    return check_error(-1, errInfo);	}        /*         * Root directories (such as C:\ or \\server\share\ are fabricated.         */	strcpy(buffer,name);	return 1;    }	    strcpy(buffer,wfd.cAlternateFileName);    if (!*buffer) {	strcpy(buffer,wfd.cFileName);    }    return 1;}intefile_link(Efile_error* errInfo, char* old, char* new){    errno = ENOTSUP;    return check_error(-1, errInfo);}intefile_symlink(Efile_error* errInfo, char* old, char* new){    errno = ENOTSUP;    return check_error(-1, errInfo);}

⌨️ 快捷键说明

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