summaryrefslogtreecommitdiffstats
path: root/lib/base/file.cpp
diff options
context:
space:
mode:
authorcvsadm <cvsadm>2005-01-21 00:44:34 +0000
committercvsadm <cvsadm>2005-01-21 00:44:34 +0000
commitb2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch)
treecf58939393a9032182c4fbc4441164a9456e82f8 /lib/base/file.cpp
downloadds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.gz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.xz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.zip
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'lib/base/file.cpp')
-rw-r--r--lib/base/file.cpp702
1 files changed, 702 insertions, 0 deletions
diff --git a/lib/base/file.cpp b/lib/base/file.cpp
new file mode 100644
index 00000000..7382be46
--- /dev/null
+++ b/lib/base/file.cpp
@@ -0,0 +1,702 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * file.c: system specific functions for reading/writing files
+ *
+ * See file.h for formal definitions of what these functions do
+ *
+ * Rob McCool
+ */
+
+
+#include "base/file.h"
+#include "ereport.h"
+#ifdef BSD_RLIMIT
+#include <sys/time.h>
+#include <sys/resource.h>
+#else
+#include <stdlib.h>
+#include <signal.h>
+#endif
+#ifdef XP_WIN32
+#include <time.h> /* time */
+#include <sys/stat.h> /* stat */
+#include <errno.h>
+#include <direct.h>
+#include <base/nterr.h>
+/* Removed for ns security integration
+#include <xp_error.h>
+*/
+#endif
+#include <prerror.h>
+
+#include "private/pprio.h"
+#include "prlock.h"
+
+extern "C" char *nscperror_lookup(int err);
+
+/* --- globals -------------------------------------------------------------*/
+/* PRFileDesc * SYS_ERROR_FD = NULL; */
+
+const int errbuf_size = 256;
+const unsigned int LOCKFILERANGE=0x7FFFFFFF;
+PRLock *_atomic_write_lock = NULL;
+
+/* --------------------------------- stat --------------------------------- */
+
+
+ /* XXXMB - Can't convert to PR_GetFileInfo because we directly exported
+ * the stat interface... Damn.
+ */
+NSAPI_PUBLIC int system_stat(char *path, struct stat *finfo)
+{
+#ifdef XP_WIN32
+
+ int chop, l;
+
+/* The NT stat is very peculiar about directory names. */
+/* XXX aruna - there is a bug here, maybe in the C runtime.
+ * Stating the same path in a separate program succeeds. From
+ * jblack's profiling, this needs to be replaced by the Win32
+ * calls anyway.*/
+
+ l = strlen(path);
+ if((path[l - 1] == '/') &&
+ (!(isalpha(path[0]) && (!strcmp(&path[1], ":/")))))
+ {
+ chop = 1;
+ path[--l] = '\0';
+ }
+ else chop = 0;
+#endif /* XP_WIN32 */
+
+#ifdef XP_UNIX
+ if(stat(path, finfo) == -1)
+ return -1;
+#else /* XP_WIN32 */
+
+ if(_stat(path, (struct _stat *)finfo) == -1) {
+ /* XXXMB - this sucks;
+ * try to convert to an error code we'll expect...
+ */
+ switch(errno) {
+ case ENOENT: PR_SetError(PR_FILE_NOT_FOUND_ERROR, errno); break;
+ default: PR_SetError(PR_UNKNOWN_ERROR, errno); break;
+ }
+ return -1;
+ }
+
+ /* NT sets the time fields to -1 if it thinks that the file
+ * is a device ( like com1.html, lpt1.html etc) In this case
+ * simply set last modified time to the current time....
+ */
+
+ if (finfo->st_mtime == -1) {
+ finfo->st_mtime = time(NULL);
+ }
+ if (finfo->st_atime == -1) {
+ finfo->st_atime = 0;
+ }
+ if (finfo->st_ctime == -1) {
+ finfo->st_ctime = 0;
+ }
+ if(chop)
+ path[l++] = '/';
+
+#endif /* XP_WIN32 */
+
+ if(S_ISREG(finfo->st_mode) && (path[strlen(path) - 1] == '/')) {
+ /* File with trailing slash */
+ errno = ENOENT;
+ return -1;
+ }
+ return 0;
+}
+
+
+NSAPI_PUBLIC int system_fread(SYS_FILE fd, char *buf, int sz)
+{
+ /* XXXMB - this is the *one* function which does return a length
+ * instead of the IO_ERROR/IO_OKAY.
+ */
+ return PR_Read(fd, buf, sz);
+}
+
+NSAPI_PUBLIC int system_fwrite(SYS_FILE fd, char *buf, int sz) {
+ int n,o,w;
+
+ for(n=sz,o=0; n; n-=w,o+=w) {
+ if((w = PR_Write(fd, &buf[o], n)) < 0)
+ return IO_ERROR;
+ }
+ return IO_OKAY;
+}
+
+/* ---------------------------- Standard UNIX ----------------------------- */
+
+#ifdef XP_UNIX
+
+#include <sys/file.h> /* flock */
+
+NSAPI_PUBLIC int system_fwrite_atomic(SYS_FILE fd, char *buf, int sz)
+{
+ int ret;
+#if 0
+ if(flock(fd,LOCK_EX) == -1)
+ return IO_ERROR;
+#endif
+ ret = system_fwrite(fd,buf,sz);
+#if 0
+ if(flock(fd,LOCK_UN) == -1)
+ return IO_ERROR; /* ??? */
+#endif
+ return ret;
+}
+
+/* -------------------------- system_nocoredumps -------------------------- */
+
+
+NSAPI_PUBLIC int system_nocoredumps(void)
+{
+#ifdef BSD_RLIMIT
+ struct rlimit rl;
+
+ rl.rlim_cur = 0;
+ rl.rlim_max = 0;
+ return setrlimit(RLIMIT_CORE, &rl);
+#else
+#if defined(SNI)
+/* C++ compiler seems to find more that one overloaded instance of exit() ?! */
+#define EXITFUNC ::exit
+#else
+#define EXITFUNC exit
+#endif
+ signal(SIGQUIT, EXITFUNC);
+ signal(SIGILL, EXITFUNC);
+ signal(SIGTRAP, EXITFUNC);
+ signal(SIGABRT, EXITFUNC);
+ signal(SIGIOT, EXITFUNC);
+ signal(SIGEMT, EXITFUNC);
+ signal(SIGFPE, EXITFUNC);
+ signal(SIGBUS, EXITFUNC);
+ signal(SIGSEGV, EXITFUNC);
+ signal(SIGSYS, EXITFUNC);
+
+
+ return 0;
+#endif
+}
+#endif /* XP_UNIX */
+
+/* --------------------------- file_setinherit ---------------------------- */
+
+NSAPI_PUBLIC int file_setinherit(SYS_FILE fd, int value)
+{
+#if defined(XP_WIN32)
+ int ret;
+
+// ret = SetHandleInformation((HANDLE)PR_FileDesc2NativeHandle(fd), 0, value?HANDLE_FLAG_INHERIT:0);
+ // This function did nothing before since the mask was set to 0.
+ ret = SetHandleInformation((HANDLE)PR_FileDesc2NativeHandle(fd), HANDLE_FLAG_INHERIT, value?HANDLE_FLAG_INHERIT:0);
+ return ret==0?-1:0;
+#elif defined(XP_UNIX)
+ int flags = 0;
+ PRInt32 nativeFD;
+ PRFileDesc *bottom = fd;
+
+ while (bottom->lower != NULL) {
+ bottom = bottom->lower;
+ }
+
+ nativeFD = PR_FileDesc2NativeHandle(bottom);
+#if 0
+fprintf(stderr, "\nInfo(file_setinherit): Native file descriptor is %d\n", nativeFD);
+#endif
+ flags = fcntl(nativeFD, F_GETFD, 0);
+ if(flags == -1)
+ return -1;
+ if(value)
+ flags &= (~FD_CLOEXEC);
+ else
+ flags |= FD_CLOEXEC;
+ fcntl(nativeFD, F_SETFD, flags);
+ return 0;
+
+ /* Comment out for ns security/ nspr integration (HACK for NOW)
+ int flags = fcntl(PR_FileDesc2NativeHandle(fd), F_GETFD, 0);
+ if(flags == -1)
+ return -1;
+ if(value)
+ flags &= (~FD_CLOEXEC);
+ else
+ flags |= FD_CLOEXEC;
+ fcntl(PR_FileDesc2NativeHandle(fd), F_SETFD, flags);
+ return 0;
+ */
+#endif
+}
+
+NSAPI_PUBLIC SYS_FILE system_fopenRO(char *p)
+{
+ SYS_FILE f = PR_Open(p, PR_RDONLY, 0);
+
+ if (!f)
+ return SYS_ERROR_FD;
+ return f;
+}
+
+NSAPI_PUBLIC SYS_FILE system_fopenWA(char *p)
+{
+ SYS_FILE f = PR_Open(p, PR_RDWR|PR_CREATE_FILE|PR_APPEND, 0644);
+
+ if (!f)
+ return SYS_ERROR_FD;
+ return f;
+}
+
+NSAPI_PUBLIC SYS_FILE system_fopenRW(char *p)
+{
+ SYS_FILE f = PR_Open(p, PR_RDWR|PR_CREATE_FILE, 0644);
+
+ if (!f)
+ return SYS_ERROR_FD;
+ return f;
+}
+
+NSAPI_PUBLIC SYS_FILE system_fopenWT(char *p)
+{
+ SYS_FILE f = PR_Open(p, PR_RDWR|PR_CREATE_FILE|PR_TRUNCATE, 0644);
+
+ if (!f)
+ return SYS_ERROR_FD;
+ return f;
+}
+
+NSAPI_PUBLIC int system_fclose(SYS_FILE fd)
+{
+ return (PR_Close(fd));
+}
+
+
+#ifdef FILE_WIN32
+
+int CgiBuffering;
+
+NSAPI_PUBLIC SYS_FILE system_fopen(char *path, int access, int flags)
+{
+ char p2[MAX_PATH];
+ SYS_FILE ret;
+ HANDLE fd;
+
+ if (strlen(path) >= MAX_PATH) {
+ return SYS_ERROR_FD;
+ }
+
+ file_unix2local(path, p2);
+
+ fd = CreateFile(p2, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, flags, 0, NULL);
+ ret = PR_ImportFile((int32)fd);
+
+ if(ret == INVALID_HANDLE_VALUE)
+ return SYS_ERROR_FD;
+
+ return ret;
+}
+
+
+
+NSAPI_PUBLIC int system_pread(SYS_FILE fd, char *buf, int BytesToRead) {
+ unsigned long BytesRead = 0;
+ int result = 0;
+ BOOLEAN TimeoutSet = FALSE;
+
+ /* XXXMB - nspr20 should be able to do this; but right now it doesn't
+ * return proper error info.
+ * fix it later...
+ */
+ if(ReadFile((HANDLE)PR_FileDesc2NativeHandle(fd), (LPVOID)buf, BytesToRead, &BytesRead, NULL) == FALSE) {
+ if (GetLastError() == ERROR_BROKEN_PIPE) {
+ return IO_EOF;
+ } else {
+ return IO_ERROR;
+ }
+ }
+ return (BytesRead ? BytesRead : IO_EOF);
+}
+
+NSAPI_PUBLIC int system_pwrite(SYS_FILE fd, char *buf, int BytesToWrite)
+{
+ unsigned long BytesWritten;
+
+ if (WriteFile((HANDLE)PR_FileDesc2NativeHandle(fd), (LPVOID)buf,
+ BytesToWrite, &BytesWritten, NULL) == FALSE) {
+ return IO_ERROR;
+ }
+ return BytesWritten;
+}
+
+
+NSAPI_PUBLIC int system_fwrite_atomic(SYS_FILE fd, char *buf, int sz)
+{
+ int ret;
+
+#if 0
+ if(system_flock(fd) == IO_ERROR)
+ return IO_ERROR;
+#endif
+ /* XXXMB - this is technically thread unsafe, but it catches any
+ * callers of fwrite_atomic when we're single threaded and just coming
+ * to life.
+ */
+ if (!_atomic_write_lock) {
+ _atomic_write_lock = PR_NewLock();
+ }
+ PR_Lock(_atomic_write_lock);
+ ret = system_fwrite(fd,buf,sz);
+ PR_Unlock(_atomic_write_lock);
+#if 0
+ if(system_ulock(fd) == IO_ERROR)
+ return IO_ERROR;
+#endif
+ return ret;
+}
+
+
+NSAPI_PUBLIC void file_unix2local(char *path, char *p2)
+{
+ /* Try to handle UNIX-style paths */
+ if((!strchr(path, FILE_PATHSEP))) {
+ int x;
+
+ for(x = 0; path[x]; x++)
+ p2[x] = (path[x] == '/' ? '\\' : path[x]);
+ p2[x] = '\0';
+ }
+ else
+ strcpy(p2, path);
+}
+
+
+NSAPI_PUBLIC int system_nocoredumps(void)
+{
+ return 0;
+}
+
+/* --------------------------- system_winerr ------------------------------ */
+
+
+#include <winsock.h>
+#include <errno.h>
+#include "util.h"
+
+NSAPI_PUBLIC char *system_winsockerr(void)
+{
+ int errn = WSAGetLastError();
+
+ return FindError(errn);
+}
+
+NSAPI_PUBLIC char *system_winerr(void)
+{
+ int errn = GetLastError();
+
+ if (errn == 0)
+ errn = WSAGetLastError();
+ return FindError(errn);
+}
+
+/* ------------------------- Dir related stuff ---------------------------- */
+
+
+NSAPI_PUBLIC SYS_DIR dir_open(char *pathp)
+{
+ dir_s *ret = (dir_s *) MALLOC(sizeof(dir_s));
+ char path[MAX_PATH];
+ int l;
+
+ if (strlen(pathp) >= MAX_PATH) {
+ return NULL;
+ }
+
+ l = util_sprintf(path, "%s", pathp) - 1;
+ path[strlen(pathp)] = '\0';
+ if(path[strlen(path) - 1] != FILE_PATHSEP)
+ strcpy (path + strlen(path), "\\*.*");
+ else
+ util_sprintf(path, "%s*.*", path);
+
+ ret->de.d_name = NULL;
+ if( (ret->dp = FindFirstFile(path, &ret->fdata)) != INVALID_HANDLE_VALUE)
+ return ret;
+ FREE(ret);
+ return NULL;
+}
+
+NSAPI_PUBLIC SYS_DIRENT *dir_read(SYS_DIR ds)
+{
+ if(FindNextFile(ds->dp, &ds->fdata) == FALSE)
+ return NULL;
+ if(ds->de.d_name)
+ FREE(ds->de.d_name);
+ ds->de.d_name = STRDUP(ds->fdata.cFileName);
+
+ return &ds->de;
+}
+
+NSAPI_PUBLIC void dir_close(SYS_DIR ds)
+{
+ FindClose(ds->dp);
+ if(ds->de.d_name)
+ FREE(ds->de.d_name);
+ FREE(ds);
+}
+
+#endif /* FILE_WIN32 */
+
+NSAPI_PUBLIC int file_notfound(void)
+{
+#ifdef FILE_WIN32
+ int errn = PR_GetError();
+ return (errn == PR_FILE_NOT_FOUND_ERROR);
+#else
+ return (errno == ENOENT);
+#endif
+}
+
+NSAPI_PUBLIC int dir_create_all(char *dir)
+{
+ struct stat fi;
+ char *t;
+
+#ifdef XP_WIN32
+ t = dir + 3;
+#else /* XP_UNIX */
+ t = dir + 1;
+#endif
+ while(1) {
+ t = strchr(t, FILE_PATHSEP);
+ if(t) *t = '\0';
+ if(stat(dir, &fi) == -1) {
+ if(dir_create(dir) == -1)
+ return -1;
+ }
+ if(t) *t++ = FILE_PATHSEP;
+ else break;
+ }
+ return 0;
+}
+
+
+#ifdef XP_UNIX
+#if !defined(SNI) && !defined(LINUX)
+extern char *sys_errlist[];
+#endif /* SNI */
+#endif
+
+#ifdef NET_SSL
+
+#define ERRMSG_SIZE 35
+#ifdef THREAD_ANY
+static int errmsg_key = -1;
+#include "systhr.h"
+/* Removed for ns security integration
+#include "xp_error.h"
+*/
+#else
+static char errmsg[ERRMSG_SIZE];
+#endif
+
+#include "util.h"
+
+static char *_errmsg_new(int code)
+{
+ char *ret;
+#ifdef THREAD_ANY
+ if(!(ret = (char *) systhread_getdata(errmsg_key))) {
+ ret = (char *) PERM_MALLOC(256);
+ systhread_setdata(errmsg_key, (void *)ret);
+ }
+#else
+ ret = errmsg;
+#endif
+ util_snprintf(ret, ERRMSG_SIZE, "libsec code %d", code);
+#ifndef MCC_BATMAN
+ PR_SetError(0,0);
+#endif
+ return ret;
+}
+#endif
+
+
+void system_errmsg_init(void)
+{
+ if (errmsg_key == -1) {
+#if defined(THREAD_ANY) && defined(NET_SSL)
+ errmsg_key = systhread_newkey();
+#endif
+#ifdef XP_WIN32
+ HashNtErrors();
+#endif
+ if (!_atomic_write_lock)
+ _atomic_write_lock = PR_NewLock();
+ }
+}
+
+NSAPI_PUBLIC int system_errmsg_fn(char **buff, size_t maxlen)
+{
+ char static_error[128];
+ char *lmsg = 0; /* Local message pointer */
+ size_t msglen = 0;
+ int sys_error = 0;
+ PRErrorCode nscp_error;
+#ifdef XP_WIN32
+ LPTSTR sysmsg = 0;
+#endif
+
+
+ /* Grab the OS error message */
+#ifdef XP_WIN32
+ sys_error = GetLastError();
+#else
+ sys_error = errno;
+#endif
+ nscp_error = PR_GetError();
+
+ /* If there is a NSPR error, but it is "unknown", try to get the OSError
+ * and use that instead.
+ */
+ if (nscp_error == PR_UNKNOWN_ERROR)
+ errno = PR_GetOSError();
+
+ if (nscp_error != 0 && nscp_error != PR_UNKNOWN_ERROR){
+ char *nscp_error_msg;
+
+ nscp_error_msg = nscperror_lookup(nscp_error);
+ if(nscp_error_msg){
+ PR_SetError(0, 0);
+ lmsg = nscp_error_msg;
+ } else {
+ util_snprintf(static_error, ERRMSG_SIZE, "unknown error %d", nscp_error);
+ lmsg = static_error;
+ }
+ } else {
+#if defined(XP_WIN32)
+ msglen = FormatMessage(
+ FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL,
+ GetLastError(),
+ LOCALE_SYSTEM_DEFAULT,
+ (LPTSTR)&sysmsg,
+ 0,
+ 0);
+ if (msglen > 0)
+ lmsg = sysmsg;
+ else
+ lmsg = system_winerr();
+ SetLastError(0);
+#else
+/* replaced
+#if defined(SNI) || defined(LINUX)
+ / C++ platform has no definition for sys_errlist /
+ lmsg = strerror(errno);
+#else
+ lmsg = sys_errlist[errno];
+#endif
+with lmsg =strerror(errno);*/
+ lmsg=strerror(errno);
+ errno = 0;
+#endif
+ }
+
+ /* At this point lmsg points to something. */
+ msglen = strlen(lmsg);
+
+ if (*buff == NULL)
+ *buff = STRDUP(lmsg);
+ else if (maxlen > msglen)
+ memcpy(*buff, lmsg, msglen+1);
+ else
+ msglen = 0;
+
+#ifdef XP_WIN32
+ /* NT's FormatMessage() dynamically allocated the msg; free it */
+ if (sysmsg)
+ LocalFree(sysmsg);
+#endif
+
+ return msglen;
+}
+
+NSAPI_PUBLIC char *
+system_errmsg(void)
+{
+ char *buff = 0;
+
+ if (errmsg_key == -1)
+ return "unknown early startup error";
+
+ // rmaxwell - This is extremely lame.
+ // Allocate a buffer in thread local storage to
+ // hold the last error message.
+ // The whole error message facility is broken and should be
+ // updated to get error strings out of the code.
+ if(!(buff = (char *) systhread_getdata(errmsg_key))) {
+ buff = (char *) PERM_MALLOC(errbuf_size);
+ systhread_setdata(errmsg_key, (void *)buff);
+ }
+ system_errmsg_fn(&buff, errbuf_size);
+ if (buff == 0)
+ buff = "Could not retrieve system error message";
+ return buff;
+}
+
+NSAPI_PUBLIC int
+system_rename(char *oldpath, char *newpath)
+{
+ return rename(oldpath, newpath);
+}
+
+NSAPI_PUBLIC int
+system_unlink(char *path)
+{
+ return PR_Delete(path)==PR_FAILURE?-1:0;
+}
+
+NSAPI_PUBLIC int system_lseek(SYS_FILE fd, int off, int wh)
+{
+ switch (wh) {
+ case 0:
+ return PR_Seek(fd, off, PR_SEEK_SET);
+ break;
+ case 1:
+ return PR_Seek(fd, off, PR_SEEK_CUR);
+ break;
+ case 2:
+ return PR_Seek(fd, off, PR_SEEK_END);
+ break;
+ default:
+ return -1;
+ }
+}
+
+NSAPI_PUBLIC int
+system_tlock(SYS_FILE fd)
+{
+ return PR_TLockFile(fd);
+}
+
+NSAPI_PUBLIC int
+system_flock(SYS_FILE fd)
+{
+ return PR_LockFile(fd);
+}
+
+NSAPI_PUBLIC int
+system_ulock(SYS_FILE fd)
+{
+ return PR_UnlockFile(fd);
+}