diff --git a/lib/isc/win32/condition.c b/lib/isc/win32/condition.c index 586732ed4b..e84776755f 100644 --- a/lib/isc/win32/condition.c +++ b/lib/isc/win32/condition.c @@ -15,15 +15,17 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: condition.c,v 1.15 2001/01/09 21:58:48 bwelling Exp $ */ +/* $Id: condition.c,v 1.16 2001/07/06 05:05:51 mayer Exp $ */ #include #include #include +#include +#include -#define SIGNAL 0 -#define BROADCAST 1 +#define LSIGNAL 0 +#define LBROADCAST 1 isc_result_t isc_condition_init(isc_condition_t *cond) { @@ -37,14 +39,14 @@ isc_condition_init(isc_condition_t *cond) { /* XXX */ return (ISC_R_UNEXPECTED); } - cond->events[SIGNAL] = h; + cond->events[LSIGNAL] = h; h = CreateEvent(NULL, TRUE, FALSE, NULL); if (h == NULL) { - (void)CloseHandle(cond->events[SIGNAL]); + (void)CloseHandle(cond->events[LSIGNAL]); /* XXX */ return (ISC_R_UNEXPECTED); } - cond->events[BROADCAST] = h; + cond->events[LBROADCAST] = h; return (ISC_R_SUCCESS); } @@ -59,7 +61,7 @@ isc_condition_signal(isc_condition_t *cond) { REQUIRE(cond != NULL); if (cond->waiters > 0 && - !SetEvent(cond->events[SIGNAL])) { + !SetEvent(cond->events[LSIGNAL])) { /* XXX */ return (ISC_R_UNEXPECTED); } @@ -77,7 +79,7 @@ isc_condition_broadcast(isc_condition_t *cond) { REQUIRE(cond != NULL); if (cond->waiters > 0 && - !SetEvent(cond->events[BROADCAST])) { + !SetEvent(cond->events[LBROADCAST])) { /* XXX */ return (ISC_R_UNEXPECTED); } @@ -90,8 +92,8 @@ isc_condition_destroy(isc_condition_t *cond) { REQUIRE(cond != NULL); - (void)CloseHandle(cond->events[SIGNAL]); - (void)CloseHandle(cond->events[BROADCAST]); + (void)CloseHandle(cond->events[LSIGNAL]); + (void)CloseHandle(cond->events[LBROADCAST]); return (ISC_R_SUCCESS); } @@ -110,7 +112,7 @@ wait(isc_condition_t *cond, isc_mutex_t *mutex, DWORD milliseconds) { EnterCriticalSection(mutex); cond->waiters--; if (cond->waiters == 0 && - !ResetEvent(cond->events[BROADCAST])) { + !ResetEvent(cond->events[LBROADCAST])) { /* XXX */ LeaveCriticalSection(mutex); return (ISC_R_UNEXPECTED); diff --git a/lib/isc/win32/dir.c b/lib/isc/win32/dir.c index 733acd7e9d..c17276fc0c 100644 --- a/lib/isc/win32/dir.c +++ b/lib/isc/win32/dir.c @@ -15,14 +15,30 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dir.c,v 1.8 2001/06/04 19:33:37 tale Exp $ */ +/* $Id: dir.c,v 1.9 2001/07/06 05:06:11 mayer Exp $ */ /* Principal Authors: DCL */ +/* + * isc_dir_chroot is currently stubbed out for Win32 + * This will need to be revisited + */ + +#include + #include +#include +#include +#include + +#include #include +#include #include +#include + +#include "errno2result.h" #define ISC_DIR_MAGIC ISC_MAGIC('D', 'I', 'R', '*') #define VALID_DIR(dir) ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC) @@ -218,5 +234,112 @@ isc_dir_chdir(const char *dirname) { REQUIRE(dirname != NULL); - return (ISC_R_NOTIMPLEMENTED); + if (chdir(dirname) < 0) + return (isc__errno2result(errno)); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_dir_chroot(const char *dirname) { + + return (ISC_R_SUCCESS); +} +isc_result_t +isc_dir_current(char *dirname, size_t length, isc_boolean_t end_sep) { + char *cwd; + isc_result_t result = ISC_R_SUCCESS; + + /* + * XXXDCL Could automatically allocate memory if dirname == NULL. + */ + REQUIRE(dirname != NULL); + REQUIRE(length > 0); + + cwd = getcwd(dirname, length); + + if (cwd == NULL) { + if (errno == ERANGE) + result = ISC_R_NOSPACE; + else + result = isc__errno2result(errno); + } else if (end_sep) { + if (strlen(dirname) + 1 == length) + result = ISC_R_NOSPACE; + else if (dirname[1] != '\0') + strcat(dirname, "/"); + } + + return (result); +} + +isc_result_t +isc_dir_createunique(char *templet) { + isc_result_t result; + char *x; + char *p; + int i; + int pid; + + REQUIRE(templet != NULL); + + /* + * mkdtemp is not portable, so this emulates it. + */ + + pid = getpid(); + + /* + * Replace trailing Xs with the process-id, zero-filled. + */ + for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet; + x--, pid /= 10) + *x = pid % 10 + '0'; + + x++; /* Set x to start of ex-Xs. */ + + do { + i = mkdir(templet); + i = chmod(templet, 0700); + + if (i == 0 || errno != EEXIST) + break; + + /* + * The BSD algorithm. + */ + p = x; + while (*p != '\0') { + if (isdigit(*p & 0xff)) + *p = 'a'; + else if (*p != 'z') + ++*p; + else { + /* + * Reset character and move to next. + */ + *p++ = 'a'; + continue; + } + + break; + } + + if (*p == '\0') { + /* + * Tried all combinations. errno should already + * be EEXIST, but ensure it is anyway for + * isc__errno2result(). + */ + errno = EEXIST; + break; + } + } while (1); + + if (i == -1) + result = isc__errno2result(errno); + else + result = ISC_R_SUCCESS; + + return (result); } diff --git a/lib/isc/win32/file.c b/lib/isc/win32/file.c index 1645df0ef7..dc99820991 100644 --- a/lib/isc/win32/file.c +++ b/lib/isc/win32/file.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001 Internet Software Consortium. + * Copyright (C) 2000 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,41 +15,419 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: file.c,v 1.6 2001/01/09 21:58:50 bwelling Exp $ */ +/* $Id: file.c,v 1.7 2001/07/06 05:06:25 mayer Exp $ */ -#include +#include -#undef TEMPLATE -#define TEMPLATE "tXXXXXXX.tmp" +#undef rename +#include +#include +#include +#include +#include -isc_result_t -isc_file_mktemplate(const char *file, char *buf, size_t buflen) { - char *s; +#include +#include +#include - s = ; - if ((s = strrchr(file, '\\')) != NULL) { - if ((s - file + 1 + sizeof(TEMPLATE)) > buflen) - return (ISC_R_NOSPACE); +#include +#include +#include +#include +#include - strncpy(buf, file, s - file + 1); - buf[s - file + 1] = '\0'; - strcat(buf, TEMPLATE); +#include "errno2result.h" - } else if ((s = strrchr(file, ':')) != NULL) { - if ((s - file + 2 + sizeof(TEMPLATE)) > buflen) - return (ISC_R_NOSPACE); +/* + * Emulate UNIX mkstemp, which returns an open FD to the new file + * + */ +static int +gettemp(char *path, int *doopen) { + char *start, *trv; + struct stat sbuf; + int pid; - strncpy(buf, file, s - file + 1); - buf[s - file + 1] = '\\'; - buf[s - file + 2] = '\0'; - strcat(buf, TEMPLATE); - - } else { - if (sizeof(TEMPLATE) > buflen) - return (ISC_R_NOSPACE); - - strcpy(buf, TEMPLATE); + trv = strrchr(path, 'X'); + trv++; + pid = getpid(); + /* extra X's get set to 0's */ + while (*--trv == 'X') { + *trv = (pid % 10) + '0'; + pid /= 10; + } + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + for (start = trv + 1;; --trv) { + if (trv <= path) + break; + if (*trv == '\\') { + *trv = '\0'; + if (stat(path, &sbuf)) + return(0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return(0); + } + *trv = '\\'; + break; + } } + for (;;) { + if (doopen) { + if ((*doopen = + open(path, O_CREAT|O_EXCL|O_RDWR, _S_IREAD | _S_IWRITE)) >= 0) + return(1); + if (errno != EEXIST) + return(0); + } + else if (stat(path, &sbuf)) + return(errno == ENOENT ? 1 : 0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return(0); + if (*trv == 'z') + *trv++ = 'a'; + else { + if (isdigit(*trv)) + *trv = 'a'; + else + ++*trv; + break; + } + } + } + /*NOTREACHED*/ +} + +int +mkstemp(char *path) { + int fd; + + return (gettemp(path, &fd) ? fd : -1); +} + +/* + * 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; + + if (stat(file, stats) != 0) + result = isc__errno2result(errno); + + return (result); +} + +/* isc_file_safemovefile is needed to be defined here to ensure that any file with + * the new name is renamed to a backup name and then the rename is done. If all goes + * well then the backup can be deleted, otherwise it gets renamed back. + */ + +int +isc_file_safemovefile(const char *oldname, const char *newname) { + BOOL filestatus; + char buf[512]; + struct stat sbuf; + BOOL exists = FALSE; + int tmpfd; + + /* + * Make sure we have something to do + */ + if(stat(oldname, &sbuf) != 0) { + errno = ENOENT; + return(-1); + } + + /* + * Rename to a backup the new file if it still exists + */ + if(stat(newname, &sbuf) == 0) + exists = TRUE; + + strcpy(buf, newname); + strcat(buf, ".XXXXX"); + tmpfd = mkstemp(buf); + if(tmpfd > 0) + _close(tmpfd); + DeleteFile(buf); + + if(exists == TRUE) { + _chmod(newname, _S_IREAD | _S_IWRITE); + } + + filestatus = MoveFile(newname, buf); + if(filestatus == 0) { + } + + /* Now rename the file to the new name + */ + _chmod(oldname, _S_IREAD | _S_IWRITE); + + filestatus = MoveFile(oldname, newname); + if(filestatus == 0) { + + /* Try and rename the backup back to the original name if the backup got created + */ + if(exists == TRUE) { + filestatus = MoveFile(buf, newname); + if(filestatus == 0) { + errno = EACCES; + } + } + return(-1); + } + + /* Delete the backup file if it got created + */ + if(exists == TRUE) { + filestatus = DeleteFile(buf); + } + return(0); +} + +isc_result_t +isc_file_getmodtime(const char *file, isc_time_t *time) { + isc_result_t result; + struct stat stats; + + REQUIRE(file != NULL && time != NULL); + + result = file_stats(file, &stats); + + if (result == ISC_R_SUCCESS) + /* + * XXXDCL some operating systems provide nanoseconds, too, + * such as BSD/OS via st_mtimespec. + */ + isc_time_set(time, stats.st_mtime, 0); + + return (result); +} + +isc_result_t +isc_file_settime(const char *file, isc_time_t *time) { + struct utimbuf timem; + + REQUIRE(file != NULL && time != NULL); + + /* + * tv_sec is at least a 32 bit quantity on all platforms we're + * dealing with, but it is signed on most (all?) of them, + * so we need to make sure the high bit isn't set. This unfortunately + * loses when either: + * * tv_sec becomes a signed 64 bit integer but long is 32 bits + * and isc_time_seconds > LONG_MAX, or + * * isc_time_seconds is changed to be > 32 bits but long is 32 bits + * and isc_time_seconds has at least 33 significant bits. + */ + timem.actime = timem.modtime = (long)isc_time_seconds(time); + + /* + * Here is the real check for the high bit being set. + */ + if ((timem.actime & + (1UL << (sizeof(timem.actime) * CHAR_BIT - 1))) != 0) + return (ISC_R_RANGE); + + if (utime(file, &timem) < 0) + return (isc__errno2result(errno)); + + return (ISC_R_SUCCESS); + +} + +#undef TEMPLATE +#define TEMPLATE "XXXXXXXXXX.tmp" /* 14 characters. */ + +isc_result_t +isc_file_mktemplate(const char *path, char *buf, size_t buflen) { + return (isc_file_template(path, TEMPLATE, buf, buflen)); +} + +isc_result_t +isc_file_template(const char *path, const char *templet, char *buf, + size_t buflen) { + char *s; + + REQUIRE(buf != NULL); + + s = strrchr(templet, '\\'); + if (s != NULL) + templet = s + 1; + + s = strrchr(path, '\\'); + + if (s != NULL) { + if ((s - path + 1 + strlen(templet) + 1) > buflen) + return (ISC_R_NOSPACE); + + strncpy(buf, path, s - path + 1); + buf[s - path + 1] = '\0'; + strcat(buf, templet); + } else { + if ((strlen(templet) + 1) > buflen) + return (ISC_R_NOSPACE); + + strcpy(buf, templet); + } + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_file_renameunique(const char *file, char *templet) { + int fd = -1; + int res = 0; + isc_result_t result = ISC_R_SUCCESS; + + fd = mkstemp(templet); + if (fd == -1) { + result = isc__errno2result(errno); + } + if (result == ISC_R_SUCCESS) { + res = isc_file_safemovefile(file, templet); + if (res != 0) { + result = isc__errno2result(errno); + (void)unlink(templet); + } + } + if (fd != -1) + close(fd); + return (result); +} + +isc_result_t +isc_file_openunique(char *templet, 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. + */ + fd = mkstemp(templet); + + if (fd == -1) + result = isc__errno2result(errno); + if (result == ISC_R_SUCCESS) { + f = fdopen(fd, "w+"); + if (f == NULL) { + result = isc__errno2result(errno); + (void)remove(templet); + (void)close(fd); + + } else + *fp = f; + } + + return (result); +} + +isc_result_t +isc_file_remove(const char *filename) { + int r; + + r = unlink(filename); + if (r == 0) + return (ISC_R_SUCCESS); + else + return (isc__errno2result(errno)); +} + +isc_result_t +isc_file_rename(const char *oldname, const char *newname) { + int r; + + r = isc_file_safemovefile(oldname, newname); + if (r == 0) + return (ISC_R_SUCCESS); + else + return (isc__errno2result(errno)); +} + +isc_boolean_t +isc_file_exists(const char *pathname) { + struct stat stats; + + return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS)); +} + +isc_boolean_t +isc_file_isabsolute(const char *filename) { + + /* + * Look for c:\path\... style or \\computer\shar\path... UNC style file specs + */ + return ((ISC_TF(filename[1] == ':') && ISC_TF(filename[2] == '\\')) || + (ISC_TF(filename[0] == '\\') && ISC_TF(filename[1] == '\\'))); +} + +isc_boolean_t +isc_file_iscurrentdir(const char *filename) { + return (ISC_TF(filename[0] == '.' && filename[1] == '\0')); +} + +const char * +isc_file_basename(const char *filename) { + char *s; + + s = strrchr(filename, '\\'); + if(s == NULL) + return(filename); + return(s + 1); +} + +isc_result_t +isc_file_progname(const char *filename, char *progname, size_t namelen) { + const char *s; + char *p; + size_t len; + + REQUIRE(filename != NULL); + /* + * Strip the path from the name + */ + s = isc_file_basename(filename); + if(s == NULL) { + return(ISC_R_NOSPACE); + } + + /* + * Strip any and all suffixes + */ + p = strchr(s, '.'); + if(p == NULL) { + if(namelen <= strlen(s)) + return(ISC_R_NOSPACE); + + strcpy(progname, s); + return(ISC_R_SUCCESS); + } + + /* + * Copy the result to the buffer + */ + len = p - s; + if(len >= namelen) + return(ISC_R_NOSPACE); + + strncpy(progname, s, len); + progname[len] = '\0'; return(ISC_R_SUCCESS); } diff --git a/lib/isc/win32/fsaccess.c b/lib/isc/win32/fsaccess.c index 126b626488..e397694640 100644 --- a/lib/isc/win32/fsaccess.c +++ b/lib/isc/win32/fsaccess.c @@ -15,18 +15,29 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: fsaccess.c,v 1.6 2001/01/09 21:58:51 bwelling Exp $ */ - -#include -#include -#include +/* $Id: fsaccess.c,v 1.8 2001/07/08 05:09:01 mayer Exp $ */ /* - * This file is entirely theoretical. It has never been compiled or tested. - * At the very least, even if this is all perfect (HAH!), isc__winerror2result - * needs to be written. + * Note that Win32 does not have the concept of files having access and ownership + * bits. The FAT File system only has a readonly flag for everyone and that's + * all. NTFS uses ACL's which is a totally different concept of controlling + * access. + * + * This code needs to be revisited to set up proper access control for NTFS file systems. + * Nothing can be done for FAT file systems. */ +#include + +#include +#include +#include +#include + +#include + +#include "errno2result.h" + /* * The OS-independent part of the API is in lib/isc. */ @@ -34,145 +45,64 @@ isc_result_t isc_fsaccess_set(const char *path, isc_fsaccess_t access) { - isc_result_t result; - isc_fsaccess_t bits, mask; + struct stat statb; + int mode; isc_boolean_t is_dir = ISC_FALSE; - int i; - DWORD winerror; - PACL dacl; - PSID psid[3]; -#define owner psid[0] -#define group psid[1] -#define world psid[2] - PSECURITY_DESCRIPTOR sd; - EXPLICIT_ACCESS ea[3], *pea; - TRUSTEETYPE trustee_type[3] = { - TRUSTEE_IS_USER, TRUSTEE_IS_GROUP, TRUSTEE_IS_WELL_KNOWN_GROUP - }; + isc_fsaccess_t bits; + isc_result_t result; - owner = group = world = dacl = sd = NULL; + 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); - /* XXXDCL -- NEED TO SET is_dir! Maybe use stat; what is native way? */ result = check_bad_bits(access, is_dir); if (result != ISC_R_SUCCESS) return (result); - winerror = GetNamedSecurityInfo(path, SE_FILE_OBJECT, - OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION, - &owner, &group, NULL, NULL, &sd); /* - * "ERROR_SUCCESS". Heh heh heh. + * Done with checking bad bits. Set mode_t. */ - if (winerror != ERROR_SUCCESS) - return (isc__winerror2result(winerror)); + mode = 0; - ZeroMemory(&ea, sizeof(ea)); - ea.grfAccessMode = SET_ACCESS; - ea.grfInheritance = NO_INHERITANCE; +#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); /* - * Make a mask for the number of bits per owner/group/other. - */ - for (i = mask = 0; i < ISC__FSACCESS_PERMISSIONBITS; i++) { - mask <<= 1; - mask |= 1; - } + * WIN32 doesn't have the concept of execute bits. We leave this here + * for when we review this module. + * + bits = ISC_FSACCESS_EXECUTE | + ISC_FSACCESS_ACCESSCHILD; -#define MAP(isc, win32) \ - if ((bits & (isc)) != 0) { \ - ea.grfAccessPermissions |= (win32); \ - bits &= ~(isc); \ - } + SET_AND_CLEAR(S_IXUSR, S_IXGRP, S_IXOTH); +*/ + INSIST(access == 0); - for (i = 0; i < 2; i++) { - bits = access & mask; + if (_chmod(path, mode) < 0) + return (isc__errno2result(errno)); - pea = &ea[i]; - - pea->grfAccessPermissions = - SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES; - if (i == 0) - /* - * Owner-only permissions. - */ - pea->grfAccessPermissions |= WRITE_DAC | DELETE; - - /* - * File access rights. - */ - MAP(ISC_FSACCESS_READ, FILE_READ_DATA | FILE_READ_EA); - MAP(ISC_FSACCESS_WRITE, - FILE_WRITE_DATA | FILE_WRITE_EA | FILE_APPEND_DATA); - MAP(ISC_FSACCESS_EXECUTE, FILE_EXECUTE); - - /* - * Directory access rights. - */ - MAP(ISC_FSACCESS_LISTDIRECTORY, FILE_LIST_DIRECTORY); - MAP(ISC_FSACCESS_CREATECHILD, FILE_CREATE_CHILD); - MAP(ISC_FSACCESS_DELETECHILD, FILE_DELETE_CHILD); - MAP(ISC_FSACCESS_ACCESSCHILD, FILE_TRAVERSE); - - /* - * Ensure no other bits were set. - */ - INSIST(bits == 0); - - if (i == 2) { - /* - * Setting world. - */ - SID_IDENTIFIER_AUTHORITY authworld = - SECURITY_WORLD_SID_AUTHORITY; - - if (AllocateAndInitializeSid(&authworld, 1, - SECURITY_WORLD_RID, - 0, 0, 0, 0, 0, 0, 0, - &world) - == 0) - winerror = GetLastError(); - else - /* - * This should already be ERROR_SUCCESS. - */ - ENSURE(winerror == ERROR_SUCCESS); - - } - - if (winerror == ERROR_SUCCESS) { - BuildTrusteeWithSid(&pea->Trustee, psid[i]); - pea->Trustee.Trusteetype = trustee_type[i]; - - winerror = SetEntriesInAcl(3, ea, NULL, &dacl); - } - - if (winerror == ERROR_SUCCESS) - winerror = - SetNamedSecurityInfo(path, SE_FILE_OBJECT, - DACL_SECURITY_INFORMATION, - NULL, NULL, dacl, NULL); - - if (winerror == ERROR_SUCCESS) - access >> shift; - else - break; - } - - if (sd != NULL) - LocalFree(sd); - if (dacl != NULL) - LocalFree(dacl); - if (world != NULL) - FreeSid(world); - - if (winerror == ERROR_SUCCESS) { - /* - * Ensure no other bits were set. - */ - INSIST(access == 0); - - return (ISC_R_SUCCESS); - } else - return (isc__winerror2result(winerror)); + return (ISC_R_SUCCESS); } diff --git a/lib/isc/win32/once.c b/lib/isc/win32/once.c index 65d11b7f30..ef19d18b54 100644 --- a/lib/isc/win32/once.c +++ b/lib/isc/win32/once.c @@ -15,14 +15,17 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: once.c,v 1.6 2001/01/09 21:58:52 bwelling Exp $ */ +/* $Id: once.c,v 1.8 2001/07/08 05:09:10 mayer Exp $ */ /* Principal Authors: DCL */ +#include + #include #include #include +#include isc_result_t isc_once_do(isc_once_t *controller, void(*function)(void)) diff --git a/lib/isc/win32/stdtime.c b/lib/isc/win32/stdtime.c index d6a9c51b9c..6fadf42817 100644 --- a/lib/isc/win32/stdtime.c +++ b/lib/isc/win32/stdtime.c @@ -15,12 +15,15 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: stdtime.c,v 1.7 2001/01/09 21:58:53 bwelling Exp $ */ +/* $Id: stdtime.c,v 1.9 2001/07/08 05:09:14 mayer Exp $ */ + +#include #include #include #include +#include void isc_stdtime_get(isc_stdtime_t *t) { diff --git a/lib/isc/win32/thread.c b/lib/isc/win32/thread.c index 01744ea78e..1a79ce3a5f 100644 --- a/lib/isc/win32/thread.c +++ b/lib/isc/win32/thread.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: thread.c,v 1.14 2001/01/09 21:58:55 bwelling Exp $ */ +/* $Id: thread.c,v 1.15 2001/07/06 05:07:54 mayer Exp $ */ #include @@ -58,3 +58,11 @@ isc_thread_join(isc_thread_t thread, isc_threadresult_t *rp) { return (ISC_R_SUCCESS); } + +void +isc_thread_setconcurrency(unsigned int level) { + +/* + * This is unnecessary on Win32 systems + */ +} diff --git a/lib/isc/win32/time.c b/lib/isc/win32/time.c index 5f2d17ddcb..7ca8ac9c06 100644 --- a/lib/isc/win32/time.c +++ b/lib/isc/win32/time.c @@ -15,7 +15,18 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: time.c,v 1.20 2001/01/09 21:58:56 bwelling Exp $ */ +/* $Id: time.c,v 1.21 2001/07/06 05:07:44 mayer Exp $ */ + +/* + * Windows has a different epoch than Unix. Therefore this code sets the epoch + * value to the Unix epoch. Care should be used when using these routines to + * ensure that this difference is taken into account. System and File times + * may require adjusting for this when modifying any time value that needs + * to be an absolute Windows time. + * + * Currently only epoch-specific code and the isc_time_seconds + * and isc_time_secondsastimet use the epoch-adjusted code. + */ #include @@ -30,6 +41,7 @@ #include #include +#include /* * struct FILETIME uses "100-nanoseconds intervals". @@ -40,8 +52,23 @@ #define NS_PER_S 1000000000 #define NS_INTERVAL 100 #define INTERVALS_PER_S (NS_PER_S / NS_INTERVAL) -#define UINT64_MAX 0xffffffffffffffffui64 +#define UINT64_MAX _UI64_MAX +/*** + *** Absolute Times + ***/ + +static isc_time_t epoch = { 0, 0 }; +isc_time_t *isc_time_epoch = &epoch; + +void +TimetToFileTime(time_t t, LPFILETIME pft) { + LONGLONG i; + + i = Int32x32To64(t, 10000000) + 116444736000000000; + pft->dwLowDateTime = (DWORD) i; + pft->dwHighDateTime = (DWORD) (i >>32); +} /*** *** Intervals ***/ @@ -60,7 +87,7 @@ isc_interval_set(isc_interval_t *i, */ REQUIRE(i != NULL); - REQUIRE(nanoseconds < 1000000000); + REQUIRE(nanoseconds < NS_PER_S); i->interval = (LONGLONG)seconds * INTERVALS_PER_S + nanoseconds / NS_INTERVAL; @@ -81,13 +108,6 @@ isc_interval_iszero(isc_interval_t *i) { } -/*** - *** Absolute Times - ***/ - -static isc_time_t epoch = { 0, 0 }; -isc_time_t *isc_time_epoch = &epoch; - void isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) { ULARGE_INTEGER i; @@ -97,7 +117,7 @@ isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) { * epoch. */ REQUIRE(t != NULL); - REQUIRE(nanoseconds < 1000000000); + REQUIRE(nanoseconds < NS_PER_S); i.QuadPart = (LONGLONG)seconds * INTERVALS_PER_S + nanoseconds / NS_INTERVAL; @@ -107,6 +127,11 @@ isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) { } +void +isc_time_initepoch() { + TimetToFileTime(0, &epoch.absolute); +} + void isc_time_settoepoch(isc_time_t *t) { /* @@ -115,20 +140,21 @@ isc_time_settoepoch(isc_time_t *t) { REQUIRE(t != NULL); - t->absolute.dwLowDateTime = 0; - t->absolute.dwHighDateTime = 0; + t->absolute.dwLowDateTime = epoch.absolute.dwLowDateTime; + t->absolute.dwHighDateTime = epoch.absolute.dwHighDateTime; } isc_boolean_t isc_time_isepoch(isc_time_t *t) { + /* * Returns ISC_TRUE iff. 't' is the epoch ("time zero"). */ REQUIRE(t != NULL); - if (t->absolute.dwLowDateTime == 0 && - t->absolute.dwHighDateTime == 0) + if (t->absolute.dwLowDateTime == epoch.absolute.dwLowDateTime && + t->absolute.dwHighDateTime == epoch.absolute.dwHighDateTime) return (ISC_TRUE); return (ISC_FALSE); @@ -136,6 +162,8 @@ isc_time_isepoch(isc_time_t *t) { isc_result_t isc_time_now(isc_time_t *t) { + + char dtime[10]; /* * Set *t to the current absolute time. */ @@ -144,6 +172,7 @@ isc_time_now(isc_time_t *t) { GetSystemTimeAsFileTime(&t->absolute); + _strtime(dtime); return (ISC_R_SUCCESS); } @@ -163,7 +192,7 @@ isc_time_nowplusinterval(isc_time_t *t, isc_interval_t *i) { i1.LowPart = t->absolute.dwLowDateTime; i1.HighPart = t->absolute.dwHighDateTime; - if (UINT64_MAX - i1.QuadPart < i->interval) + if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval) return (ISC_R_RANGE); i1.QuadPart += i->interval; @@ -198,7 +227,7 @@ isc_time_add(isc_time_t *t, isc_interval_t *i, isc_time_t *result) { i1.LowPart = t->absolute.dwLowDateTime; i1.HighPart = t->absolute.dwHighDateTime; - if (UINT64_MAX - i1.QuadPart < i->interval) + if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval) return (ISC_R_RANGE); i1.QuadPart += i->interval; @@ -222,13 +251,15 @@ isc_time_subtract(isc_time_t *t, isc_interval_t *i, isc_time_t *result) { i1.LowPart = t->absolute.dwLowDateTime; i1.HighPart = t->absolute.dwHighDateTime; - if (i.QuadPart < i->interval) + if (i1.QuadPart < (unsigned __int64) i->interval) return (ISC_R_RANGE); i1.QuadPart -= i->interval; result->absolute.dwLowDateTime = i1.LowPart; result->absolute.dwHighDateTime = i1.HighPart; + + return (ISC_R_SUCCESS); } isc_uint64_t @@ -254,16 +285,21 @@ isc_time_microdiff(isc_time_t *t1, isc_time_t *t2) { return (i3); } +/* + * Note that the value returned is the seconds relative to the Unix epoch rather than + * the seconds since Windows epoch. + * This is for compatibility with the Unix side. + */ isc_uint32_t isc_time_seconds(isc_time_t *t) { ULARGE_INTEGER i; REQUIRE(t != NULL); - i.LowPart = t->absolute.dwLowDateTime; - i.HighPart = t->absolute.dwHighDateTime; + i.LowPart = t->absolute.dwLowDateTime - epoch.absolute.dwLowDateTime; + i.HighPart = t->absolute.dwHighDateTime - epoch.absolute.dwHighDateTime; - INSIST(i.QuadPart / INTERVALS_PER_S <= (isc_uint32_t)-1); +// INSIST(i.QuadPart / INTERVALS_PER_S <= (isc_uint32_t)-1); return ((isc_uint32_t)(i.QuadPart / INTERVALS_PER_S)); } @@ -278,6 +314,14 @@ isc_time_secondsastimet(isc_time_t *t, time_t *secondsp) { i1.LowPart = t->absolute.dwLowDateTime; i1.HighPart = t->absolute.dwHighDateTime; + /* + * Get the time_t zero equivalent in FILETIME + * The zero point for FILETIME is 1 January, 1601 + * while for timet it is 1 January, 1970 + */ + i1.LowPart -= epoch.absolute.dwLowDateTime; + i1.HighPart -= epoch.absolute.dwHighDateTime; + i1.QuadPart /= INTERVALS_PER_S; /* @@ -363,16 +407,13 @@ isc_time_secondsastimet(isc_time_t *t, time_t *secondsp) { isc_uint32_t isc_time_nanoseconds(isc_time_t *t) { - ULARGE_INTEGER i; + SYSTEMTIME st; - REQUIRE(t != NULL); + /* + * Convert the time to a SYSTEMTIME structure and the grab the + * milliseconds + */ + FileTimeToSystemTime(&t->absolute, &st); - i.LowPart = t->absolute.dwLowDateTime; - i.HighPart = t->absolute.dwHighDateTime; - - i.QuadPart -= isc_time_seconds(t); - - ENSURE(i.QuadPart * NS_INTERVAL < NS); - - return ((isc_uint32_t)(i.QuadPart * NS_INTERVAL)); + return ((isc_uint32_t)(st.wMilliseconds * 1000000)); }