/* opendir() - The case insensitive version of opendir */ DIR * opendir(const char *path) { DIR *tDir; HANDLE tH; char tPath[MAX_PATH]; WIN32_FIND_DATA tData; int ntErr; (void)strcpy(tPath, path); (void)strcat(tPath, "\\*"); tH = FindFirstFile(tPath, &tData); if (tH == INVALID_HANDLE_VALUE) { ntErr = GetLastError(); switch (ntErr) { case ERROR_DIRECTORY: errno = ENOTDIR; return (DIR *) 0; case ERROR_BAD_PATHNAME: /* AFS NT client returns ERROR_BAD_PATHNAME where it should return * ERROR_DIRECTORY. */ case ERROR_FILE_NOT_FOUND: /* If at the "root" directory, then this can happen if it's empty. */ { struct stat status; size_t len = strlen(tPath) - 1; tPath[len] = '\0'; if (len >= 2 && tPath[len - 2] != ':') { tPath[len - 1] = '\0'; } if (stat(tPath, &status) < 0) { errno = nterr_nt2unix(GetLastError(), ENOENT); return (DIR *) 0; } if (!(status.st_mode & _S_IFDIR)) { errno = ENOTDIR; return (DIR *) 0; } } break; default: errno = nterr_nt2unix(GetLastError(), ENOENT); return (DIR *) 0; } } tDir = calloc(1, sizeof(DIR)); if (!tDir) { errno = ENOMEM; } else { tDir->h = tH; tDir->data = tData; } return tDir; }
int nt_seek(FD_t fd, afs_foff_t off, int whence) { int code; LARGE_INTEGER offset; int where; if (SEEK_SET == whence) { where = FILE_BEGIN; } else if (SEEK_END == whence) { where = FILE_END; } else if (SEEK_CUR == whence) { where = FILE_CURRENT; } else { errno = EINVAL; return -1; } offset.QuadPart = off; code = SetFilePointerEx(fd, offset, NULL, where); if (0 == code) { errno = nterr_nt2unix(GetLastError(), EBADF); return -1; } return 0; }
int nt_sync(int cdrive) { FD_t drive_fd; char sdrive[32]; int n; n = cdrive; if (n <= 26) { cdrive = 'A' + (n - 1); } cdrive = _toupper(cdrive); (void)sprintf(sdrive, "\\\\.\\%c:", cdrive); drive_fd = nt_open(sdrive, O_RDWR, 0666); if (drive_fd == INVALID_FD) { return -1; } if (!FlushFileBuffers((HANDLE) drive_fd)) { errno = nterr_nt2unix(GetLastError(), EBADF); nt_close(drive_fd); return -1; } nt_close(drive_fd); return 0; }
int nt_pread(FD_t fd, void * buf, afs_sfsize_t count, afs_foff_t offset) { /* * This really ought to call NtReadFile */ DWORD nbytes; BOOL code; OVERLAPPED overlap = {0}; LARGE_INTEGER liOffset; /* * Cast through a LARGE_INTEGER - make no assumption about * byte ordering and leave that to the compiler.. */ liOffset.QuadPart = offset; overlap.Offset = liOffset.LowPart; overlap.OffsetHigh = liOffset.HighPart; code = ReadFile((HANDLE) fd, (void *)buf, (DWORD) count, &nbytes, &overlap); if (!code) { DWORD gle = GetLastError(); if (gle != ERROR_HANDLE_EOF) { errno = nterr_nt2unix(GetLastError(), EBADF); return -1; } } return (ssize_t)nbytes; }
/* * vpt_RemoveEntry() -- Remove vice partition table entry. * * RETURN CODES: 0 success, -1 failed (errno set) */ int vpt_RemoveEntry(const char *vpname) { long status; HKEY tabKey; if (!vpt_PartitionNameValid(vpname)) { errno = EINVAL; return -1; } /* open canonical Afstab key */ status = RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_SVR_SVC_AFSTAB_KEY, KEY_WRITE, 0, &tabKey, NULL); if (status == ERROR_SUCCESS) { /* delete key representing vice partition */ status = RegDeleteKey(tabKey, vpname); } if (status) { errno = nterr_nt2unix(status, EIO); return -1; } return 0; }
/* Currently nt_ftruncate only tested to shrink a file. */ int nt_ftruncate(FD_t fd, afs_foff_t len) { LARGE_INTEGER length; length.QuadPart = len; if (SetFilePointerEx(fd, length, NULL, FILE_BEGIN) == 0xffffffff) { errno = nterr_nt2unix(GetLastError(), EBADF); return -1; } if (!SetEndOfFile(fd)) { errno = nterr_nt2unix(GetLastError(), EBADF); return -1; } return 0; }
int nt_close(FD_t fd) { BOOL code; code = CloseHandle(fd); if (!code) { errno = nterr_nt2unix(GetLastError(), EBADF); return -1; } return 0; }
/* nt_open - open an NT handle for a file. * * Return Value: * the handle or -1 on error. */ FD_t nt_open(const char *name, int flags, int mode) { HANDLE fh; DWORD nt_access = 0; DWORD nt_share = FILE_SHARE_READ; DWORD nt_create = 0; /* Really use the sequential one for data files, random for meta data. */ DWORD FandA = BASEFILEATTRIBUTE | FILE_FLAG_SEQUENTIAL_SCAN; /* set access */ if ((flags & O_RDWR) || (flags & O_WRONLY)) { nt_access |= GENERIC_WRITE; nt_share |= FILE_SHARE_WRITE | FILE_SHARE_DELETE; } if ((flags & O_RDWR) || (flags == O_RDONLY)) nt_access |= GENERIC_READ; /* set creation */ switch (flags & (O_CREAT | O_EXCL | O_TRUNC)) { case 0: nt_create = OPEN_EXISTING; break; case O_CREAT: nt_create = OPEN_ALWAYS; break; case O_CREAT | O_TRUNC: nt_create = CREATE_ALWAYS; break; case O_CREAT | O_EXCL: case O_CREAT | O_EXCL | O_TRUNC: nt_create = CREATE_NEW; break; case O_TRUNC: nt_create = TRUNCATE_EXISTING; break; case O_TRUNC | O_EXCL: case O_EXCL: default: errno = EINVAL; return INVALID_FD; break; } fh = CreateFile(name, nt_access, nt_share, NULL, nt_create, FandA, NULL); if (fh == INVALID_HANDLE_VALUE) { DWORD gle = GetLastError(); errno = nterr_nt2unix(gle, EBADF); } return fh; }
int nt_write(FD_t fd, void *buf, afs_sfsize_t size) { BOOL code; DWORD nbytes; code = WriteFile((HANDLE) fd, buf, (DWORD) size, &nbytes, NULL); if (!code) { errno = nterr_nt2unix(GetLastError(), EBADF); return -1; } return (int)nbytes; }
/* * renamefile() -- rename a file (Unix rename() semantics) */ int renamefile(const char *oldname, const char *newname) { int rc = 0; #ifdef AFS_NT40_ENV if (!MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING)) { /* rename failed */ errno = nterr_nt2unix(GetLastError(), EIO); rc = -1; } #else rc = rename(oldname, newname); #endif return rc; }
int nt_read(FD_t fd, void *buf, afs_sfsize_t size) { BOOL code; DWORD nbytes; code = ReadFile((HANDLE) fd, buf, (DWORD) size, &nbytes, NULL); if (!code) { DWORD gle = GetLastError(); if (gle != ERROR_HANDLE_EOF) { errno = nterr_nt2unix(GetLastError(), EBADF); return -1; } } return (int)nbytes; }
/* nt_unlink - unlink a case sensitive name. * * nt_unlink supports the nt_dec call. * * This nt_unlink has the delete on last close semantics of the Unix unlink * with a minor twist. Subsequent CreateFile calls on this file can succeed * if they open for delete. If a CreateFile call tries to create a new file * with the same name it will fail. Fortunately, neither case should occur * as part of nt_dec. */ int nt_unlink(char *name) { HANDLE fh; fh = CreateFile(name, GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, BASEFILEATTRIBUTE | FILE_FLAG_DELETE_ON_CLOSE | FILE_FLAG_POSIX_SEMANTICS, NULL); if (fh != INVALID_HANDLE_VALUE) CloseHandle(fh); else { errno = nterr_nt2unix(GetLastError(), ENOENT); return -1; } return 0; }
/* * vpt_AddEntry() -- Add or update vice partition table entry. * * RETURN CODES: 0 success, -1 failed (errno set) */ int vpt_AddEntry(const struct vptab *vptabp) { long status; HKEY tabKey, vpKey; const char *vpName, *vpDev; vpName = vptabp->vp_name; vpDev = vptabp->vp_dev; if (!vpt_PartitionNameValid(vpName) || !vpt_DeviceNameValid(vpDev)) { errno = EINVAL; return -1; } /* open canonical Afstab key; create if doesn't exist */ status = RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_SVR_SVC_AFSTAB_KEY, KEY_WRITE, 1 /* create */, &tabKey, NULL); if (status == ERROR_SUCCESS) { /* open key representing vice partition; create if doesn't exist */ status = RegOpenKeyAlt(tabKey, vpName, KEY_WRITE, 1 /* create */, &vpKey, NULL); if (status == ERROR_SUCCESS) { /* write partition attributes */ status = RegSetValueEx(vpKey, AFSREG_SVR_SVC_AFSTAB_DEVNAME_VALUE, 0, REG_SZ, vpDev, (DWORD)strlen(vpDev) + 1); RegCloseKey(vpKey); } RegCloseKey(tabKey); } if (status) { errno = nterr_nt2unix(status, EIO); return -1; } return 0; }
struct dirent * readdir(DIR * dir) { int rc; if (!dir) { errno = EBADF; return (struct dirent *)0; } errno = 0; if (dir->h == INVALID_HANDLE_VALUE) return (struct dirent *)0; if (dir->first) { dir->first = 0; } else { while (rc = FindNextFile(dir->h, &dir->data)) { if ((strcmp(dir->data.cFileName, ".") == 0) || (strcmp(dir->data.cFileName, "..") == 0)) { continue; /* skip "." and ".." */ } break; /* found a non '.' or '..' entry. */ } if (rc == 0) { /* FindNextFile() failed */ if (GetLastError() == ERROR_NO_MORE_FILES) return (struct dirent *)0; else { errno = nterr_nt2unix(GetLastError(), EBADF); return (struct dirent *)0; } } } dir->cdirent.d_name = dir->data.cFileName; return &dir->cdirent; }
int vpt_Start(struct vpt_iter *iterp) /* [out] iteration handle to initialize */ { long status; HKEY key; memset(iterp, 0, sizeof(*iterp)); /* open canonical Afstab key */ status = RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_SVR_SVC_AFSTAB_KEY, KEY_READ, 0, &key, NULL); if (status == ERROR_SUCCESS) { /* enumerate subkeys, each of which represents a vice partition */ status = RegEnumKeyAlt(key, &iterp->vpenum); (void)RegCloseKey(key); } if (status) { errno = nterr_nt2unix(status, EIO); return -1; } return 0; }
int nt_pwrite(FD_t fd, const void * buf, afs_sfsize_t count, afs_foff_t offset) { /* * same comment as read */ DWORD nbytes; BOOL code; OVERLAPPED overlap = {0}; LARGE_INTEGER liOffset; liOffset.QuadPart = offset; overlap.Offset = liOffset.LowPart; overlap.OffsetHigh = liOffset.HighPart; code = WriteFile((HANDLE) fd, (void *)buf, (DWORD) count, &nbytes, &overlap); if (!code) { errno = nterr_nt2unix(GetLastError(), EBADF); return -1; } return (ssize_t)nbytes; }
int vpt_NextEntry(struct vpt_iter *iterp, /* [in] valid iteration handle */ struct vptab *vptabp) /* [out] next partiton table entry */ { long status; HKEY tabKey, vpKey; char *nextNamep; if (iterp->vpenum == NULL) { /* no partition entries (or invalid iteration handle) */ errno = ENOENT; return -1; } /* find name of next partition entry to examine in multistring enum */ if (iterp->last == NULL) { /* first call */ nextNamep = iterp->last = iterp->vpenum; } else { /* subsequent call */ if (*iterp->last != '\0') { /* not at end of multistring; advance to next name */ iterp->last += strlen(iterp->last) + 1; } nextNamep = iterp->last; } if (*nextNamep == '\0') { /* end of multistring; no more entries */ errno = ENOENT; return -1; } if (strlen(nextNamep) >= VPTABSIZE_NAME) { /* invalid partition name entry */ errno = EINVAL; return -1; } strcpy(vptabp->vp_name, nextNamep); /* open canonical Afstab key */ status = RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_SVR_SVC_AFSTAB_KEY, KEY_READ, 0, &tabKey, NULL); if (status == ERROR_SUCCESS) { /* open key representing vice partition */ status = RegOpenKeyAlt(tabKey, nextNamep, KEY_READ, 0, &vpKey, NULL); if (status == ERROR_SUCCESS) { /* read partition attributes */ DWORD dataType, dataSize = VPTABSIZE_DEV; status = RegQueryValueEx(vpKey, AFSREG_SVR_SVC_AFSTAB_DEVNAME_VALUE, NULL, &dataType, vptabp->vp_dev, &dataSize); if (status == ERROR_SUCCESS && dataType != REG_SZ) { /* invalid device name type */ status = ERROR_INVALID_PARAMETER; } (void)RegCloseKey(vpKey); } (void)RegCloseKey(tabKey); } if (status) { errno = nterr_nt2unix(status, EIO); return -1; } return 0; }