static isc_result_t openuniquemode(char *templet, int mode, isc_boolean_t binary, FILE **fp) { int fd; FILE *f; isc_result_t result = ISC_R_SUCCESS; REQUIRE(templet != NULL); REQUIRE(fp != NULL && *fp == NULL); /* * Win32 does not have mkstemp. Using emulation above. */ fd = mkstemp(templet, binary); if (fd == -1) result = isc__errno2result(errno); if (result == ISC_R_SUCCESS) { #if 1 UNUSED(mode); #else (void)fchmod(fd, mode); #endif f = fdopen(fd, binary ? "wb+" : "w+"); if (f == NULL) { result = isc__errno2result(errno); (void)remove(templet); (void)close(fd); } else *fp = f; } return (result); }
isc_result_t isc_file_renameunique (const char *file, char *templet) { int fd = -1; int res = 0; isc_result_t result = ISC_R_SUCCESS; REQUIRE (file != NULL); REQUIRE (templet != NULL); fd = mkstemp (templet); if (fd == -1) result = isc__errno2result (errno); else close (fd); if (result == ISC_R_SUCCESS) { res = isc_file_safemovefile (file, templet); if (res != 0) { result = isc__errno2result (errno); (void) unlink (templet); } } return (result); }
isc_result_t isc_file_safecreate(const char *filename, FILE **fp) { isc_result_t result; int flags; struct stat sb; FILE *f; int fd; REQUIRE(filename != NULL); REQUIRE(fp != NULL && *fp == NULL); result = file_stats(filename, &sb); if (result == ISC_R_SUCCESS) { if ((sb.st_mode & S_IFREG) == 0) return (ISC_R_INVALIDFILE); flags = O_WRONLY | O_TRUNC; } else if (result == ISC_R_FILENOTFOUND) { flags = O_WRONLY | O_CREAT | O_EXCL; } else return (result); fd = open(filename, flags, S_IRUSR | S_IWUSR); if (fd == -1) return (isc__errno2result(errno)); f = fdopen(fd, "w"); if (f == NULL) { result = isc__errno2result(errno); close(fd); return (result); } *fp = f; return (ISC_R_SUCCESS); }
isc_result_t isc_file_settime(const char *file, isc_time_t *time) { int fh; REQUIRE(file != NULL && time != NULL); if ((fh = open(file, _O_RDWR | _O_BINARY)) < 0) return (isc__errno2result(errno)); /* * Set the date via the filedate system call and return. Failing * this call implies the new file times are not supported by the * underlying file system. */ if (!SetFileTime((HANDLE) _get_osfhandle(fh), NULL, &time->absolute, &time->absolute)) { close(fh); errno = EINVAL; return (isc__errno2result(errno)); } close(fh); return (ISC_R_SUCCESS); }
isc_result_t isc_fsaccess_set(const char *path, isc_fsaccess_t access) { struct stat statb; mode_t mode; isc_boolean_t is_dir = ISC_FALSE; isc_fsaccess_t bits; isc_result_t result; if (stat(path, &statb) != 0) return (isc__errno2result(errno)); if ((statb.st_mode & S_IFDIR) != 0) is_dir = ISC_TRUE; else if ((statb.st_mode & S_IFREG) == 0) return (ISC_R_INVALIDFILE); result = check_bad_bits(access, is_dir); if (result != ISC_R_SUCCESS) return (result); /* * Done with checking bad bits. Set mode_t. */ mode = 0; #define SET_AND_CLEAR1(modebit) \ if ((access & bits) != 0) { \ mode |= modebit; \ access &= ~bits; \ } #define SET_AND_CLEAR(user, group, other) \ SET_AND_CLEAR1(user); \ bits <<= STEP; \ SET_AND_CLEAR1(group); \ bits <<= STEP; \ SET_AND_CLEAR1(other); bits = ISC_FSACCESS_READ | ISC_FSACCESS_LISTDIRECTORY; SET_AND_CLEAR(S_IRUSR, S_IRGRP, S_IROTH); bits = ISC_FSACCESS_WRITE | ISC_FSACCESS_CREATECHILD | ISC_FSACCESS_DELETECHILD; SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH); bits = ISC_FSACCESS_EXECUTE | ISC_FSACCESS_ACCESSCHILD; SET_AND_CLEAR(S_IXUSR, S_IXGRP, S_IXOTH); INSIST(access == 0); if (chmod(path, mode) < 0) return (isc__errno2result(errno)); return (ISC_R_SUCCESS); }
isc_result_t isc_file_openunique(char *templet, FILE **fp) { int fd; FILE *f; isc_result_t result = ISC_R_SUCCESS; char *x; char *cp; isc_uint32_t which; int mode; REQUIRE(templet != NULL); REQUIRE(fp != NULL && *fp == NULL); cp = templet; while (*cp != '\0') cp++; if (cp == templet) return (ISC_R_FAILURE); x = cp--; while (cp >= templet && *cp == 'X') { isc_random_get(&which); *cp = alphnum[which % (sizeof(alphnum) - 1)]; x = cp--; } mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; while ((fd = open(templet, O_RDWR|O_CREAT|O_EXCL, mode)) == -1) { if (errno != EEXIST) return (isc__errno2result(errno)); for (cp = x;;) { char *t; if (*cp == '\0') return (ISC_R_FAILURE); t = strchr(alphnum, *cp); if (t == NULL || *++t == '\0') *cp++ = alphnum[0]; else { *cp = *t; break; } } } f = fdopen(fd, "w+"); if (f == NULL) { result = isc__errno2result(errno); if (remove(templet) < 0) { isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_FILE, ISC_LOG_ERROR, "remove '%s': failed", templet); } (void)close(fd); } else *fp = f; return (result); }
isc_result_t isc_fsaccess_set(const char *path, isc_fsaccess_t access) { struct stat statb; isc_boolean_t is_dir = ISC_FALSE; isc_result_t result; if (stat(path, &statb) != 0) return (isc__errno2result(errno)); if ((statb.st_mode & S_IFDIR) != 0) is_dir = ISC_TRUE; else if ((statb.st_mode & S_IFREG) == 0) return (ISC_R_INVALIDFILE); result = check_bad_bits(access, is_dir); if (result != ISC_R_SUCCESS) return (result); /* * Determine if this is a FAT or NTFS disk and * call the appropriate function to set the permissions */ if (is_ntfs(path)) return (NTFS_fsaccess_set(path, access, is_dir)); else return (FAT_fsaccess_set(path, access)); }
isc_result_t isc_file_truncate(const char *filename, isc_offset_t size) { isc_result_t result = ISC_R_SUCCESS; if (truncate(filename, size) < 0) result = isc__errno2result(errno); return (result); }
isc_result_t isc_file_truncate(const char *filename, isc_offset_t size) { int fh; REQUIRE(filename != NULL && size >= 0); if ((fh = open(filename, _O_RDWR | _O_BINARY)) < 0) return (isc__errno2result(errno)); if(_chsize(fh, size) != 0) { close(fh); return (isc__errno2result(errno)); } close(fh); return (ISC_R_SUCCESS); }
isc_result_t isc_file_renameunique(const char *file, char *templet) { char *x; char *cp; REQUIRE(file != NULL); REQUIRE(templet != NULL); cp = templet; while (*cp != '\0') cp++; if (cp == templet) return (ISC_R_FAILURE); x = cp--; while (cp >= templet && *cp == 'X') { isc_uint32_t which; isc_random_get(&which); *cp = alphnum[which % (sizeof(alphnum) - 1)]; x = cp--; } while (link(file, templet) == -1) { if (errno != EEXIST) return (isc__errno2result(errno)); for (cp = x;;) { const char *t; if (*cp == '\0') return (ISC_R_FAILURE); t = strchr(alphnum, *cp); if (t == NULL || *++t == '\0') *cp++ = alphnum[0]; else { *cp = *t; break; } } } if (unlink(file) < 0) if (errno != ENOENT) return (isc__errno2result(errno)); return (ISC_R_SUCCESS); }
isc_result_t isc_dir_chroot(const char *dirname) { REQUIRE(dirname != NULL); if (chroot(dirname) < 0) return (isc__errno2result(errno)); return (ISC_R_SUCCESS); }
isc_result_t isc_stdio_sync(FILE *f) { int r; r = _commit(_fileno(f)); if (r == 0) return (ISC_R_SUCCESS); else return (isc__errno2result(errno)); }
isc_result_t isc_stdio_flush(FILE *f) { int r; r = fflush(f); if (r == 0) return (ISC_R_SUCCESS); else return (isc__errno2result(errno)); }
isc_result_t isc_stdio_seek(FILE *f, long offset, int whence) { int r; r = fseek(f, offset, whence); if (r == 0) return (ISC_R_SUCCESS); else return (isc__errno2result(errno)); }
isc_result_t isc_file_getmodtime (const char *file, isc_time_t * time) { int fh; REQUIRE (file != NULL); REQUIRE (time != NULL); if ((fh = open (file, _O_RDONLY | _O_BINARY)) < 0) return (isc__errno2result (errno)); if (!GetFileTime ((HANDLE) _get_osfhandle (fh), NULL, NULL, &time->absolute)) { close (fh); errno = EINVAL; return (isc__errno2result (errno)); } close (fh); return (ISC_R_SUCCESS); }
isc_result_t isc_stdio_open(const char *filename, const char *mode, FILE **fp) { FILE *f; f = fopen(filename, mode); if (f == NULL) return (isc__errno2result(errno)); *fp = f; return (ISC_R_SUCCESS); }
static isc_result_t fd_stats(int fd, struct stat *stats) { isc_result_t result = ISC_R_SUCCESS; REQUIRE(stats != NULL); if (fstat(fd, stats) != 0) result = isc__errno2result(errno); return (result); }
isc_result_t isc_stdio_sync(FILE *f) { struct stat buf; int r; if (fstat(fileno(f), &buf) != 0) return (isc__errno2result(errno)); /* * Only call fsync() on regular files. */ if ((buf.st_mode & S_IFMT) != S_IFREG) return (ISC_R_SUCCESS); r = fsync(fileno(f)); if (r == 0) return (ISC_R_SUCCESS); else return (isc__errno2result(errno)); }
isc_result_t isc_file_remove(const char *filename) { int r; REQUIRE(filename != NULL); r = unlink(filename); if (r == 0) return (ISC_R_SUCCESS); else return (isc__errno2result(errno)); }
/* * XXXDCL As the API for accessing file statistics undoubtedly gets expanded, * it might be good to provide a mechanism that allows for the results * of a previous stat() to be used again without having to do another stat, * such as perl's mechanism of using "_" in place of a file name to indicate * that the results of the last stat should be used. But then you get into * annoying MP issues. BTW, Win32 has stat(). */ static isc_result_t file_stats(const char *file, struct stat *stats) { isc_result_t result = ISC_R_SUCCESS; REQUIRE(file != NULL); REQUIRE(stats != NULL); if (stat(file, stats) != 0) result = isc__errno2result(errno); return (result); }
isc_result_t isc_dir_chdir(const char *dirname) { /* * Change the current directory to 'dirname'. */ REQUIRE(dirname != NULL); if (chdir(dirname) < 0) return (isc__errno2result(errno)); return (ISC_R_SUCCESS); }
isc_result_t isc_file_rename(const char *oldname, const char *newname) { int r; REQUIRE(oldname != NULL); REQUIRE(newname != NULL); r = isc_file_safemovefile(oldname, newname); if (r == 0) return (ISC_R_SUCCESS); else return (isc__errno2result(errno)); }
isc_result_t isc_dir_chroot(const char *dirname) { REQUIRE(dirname != NULL); #ifdef HAVE_CHROOT if (chroot(dirname) < 0 || chdir("/") < 0) return (isc__errno2result(errno)); return (ISC_R_SUCCESS); #else return (ISC_R_NOTIMPLEMENTED); #endif }
isc_result_t isc_stdio_sync (FILE * f) { int r; r = fsync (fileno (f)); /* * fsync is not supported on sockets and pipes which * result in EINVAL / ENOTSUP. */ if (r == 0 || errno == EINVAL || errno == ENOTSUP) return (ISC_R_SUCCESS); else return (isc__errno2result (errno)); }
isc_result_t isc_stdio_write (const void *ptr, size_t size, size_t nmemb, FILE * f, size_t * nret) { isc_result_t result = ISC_R_SUCCESS; size_t r; clearerr (f); r = fwrite (ptr, size, nmemb, f); if (r != nmemb) result = isc__errno2result (errno); if (nret != NULL) *nret = r; return (result); }
isc_result_t isc_stdio_seek(FILE *f, off_t offset, int whence) { int r; #ifdef HAVE_FSEEKO r = fseeko(f, offset, whence); #else r = fseek(f, offset, whence); #endif if (r == 0) return (ISC_R_SUCCESS); else return (isc__errno2result(errno)); }
isc_result_t isc_stdio_seek(FILE *f, off_t offset, int whence) { int r; #ifndef _WIN64 r = fseek(f, offset, whence); #else r = _fseeki64(f, offset, whence); #endif if (r == 0) return (ISC_R_SUCCESS); else return (isc__errno2result(errno)); }
isc_result_t isc_file_isplainfilefd(int fd) { /* * This function returns success if filename is a plain file. */ struct stat filestat; memset(&filestat,0,sizeof(struct stat)); if ((fstat(fd, &filestat)) == -1) return(isc__errno2result(errno)); if(! S_ISREG(filestat.st_mode)) return(ISC_R_INVALIDFILE); return(ISC_R_SUCCESS); }
isc_result_t isc_file_isdirectory(const char *filename) { /* * This function returns success if filename is a directory. */ struct stat filestat; memset(&filestat,0,sizeof(struct stat)); if ((stat(filename, &filestat)) == -1) return(isc__errno2result(errno)); if(! S_ISDIR(filestat.st_mode)) return(ISC_R_INVALIDFILE); return(ISC_R_SUCCESS); }
isc_result_t isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret) { isc_result_t result = ISC_R_SUCCESS; size_t r; clearerr(f); r = fread(ptr, size, nmemb, f); if (r != nmemb) { if (feof(f)) result = ISC_R_EOF; else result = isc__errno2result(errno); } if (nret != NULL) *nret = r; return (result); }