diff options
Diffstat (limited to 'ghc/lib/std/cbits/openFile.c')
-rw-r--r-- | ghc/lib/std/cbits/openFile.c | 329 |
1 files changed, 0 insertions, 329 deletions
diff --git a/ghc/lib/std/cbits/openFile.c b/ghc/lib/std/cbits/openFile.c deleted file mode 100644 index e2829ff9ec..0000000000 --- a/ghc/lib/std/cbits/openFile.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998 - * - * $Id: openFile.c,v 1.20 2001/04/02 16:10:33 rrt Exp $ - * - * openFile Runtime Support - */ - -/* We use lstat, which is sadly not POSIX */ -#define NON_POSIX_SOURCE - -#include "Rts.h" -#include "stgio.h" - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif - -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif - -#if defined(mingw32_TARGET_OS) && !defined(O_NOCTTY) -#define O_NOCTTY 0 -#endif - -IOFileObject* -openStdFile(StgInt fd, StgInt rd) -{ - IOFileObject* fo; - long fd_flags; - - if ((fo = malloc(sizeof(IOFileObject))) == NULL) - return NULL; - fo->fd = fd; - fo->buf = NULL; - fo->bufWPtr = 0; - fo->bufRPtr = 0; - fo->flags = FILEOBJ_STD | ( rd ? FILEOBJ_READ : FILEOBJ_WRITE); - fo->connectedTo = NULL; - -#if !defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) - /* Set the non-blocking flag on this file descriptor. - * - * Don't do it for stdout and stderr: some shells (actually most) - * don't reset the nonblocking flag after running a program, and - * this causes all sorts of problems. --SDM (12/99) - * - * MS Win32 CRT doesn't support fcntl() -- the workaround is to - * start using 'completion ports', but I'm punting on implementing - * support for using those. - */ - if (fd != 1 && fd != 2) { - fd_flags = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK); - } -#endif - - return fo; -} - -#define OPENFILE_APPEND 0 -#define OPENFILE_WRITE 1 -#define OPENFILE_READ_ONLY 2 -#define OPENFILE_READ_WRITE 3 - -IOFileObject* -openFile(StgByteArray file, StgInt how, StgInt binary) -{ - int fd; - int oflags; - int for_writing; - int created = 0; - struct stat sb; - IOFileObject* fo; - int flags = 0; - -#if defined(_WIN32) && !(defined(__CYGWIN__) || defined(__CYGWIN32__)) -#define O_NONBLOCK 0 -#endif - - /* - * Since we aren't supposed to succeed when we're opening for writing and - * there's another writer, we can't just do an open() with O_WRONLY. - */ - - switch (how) { - case OPENFILE_APPEND: - oflags = O_NONBLOCK | O_WRONLY | O_NOCTTY | O_APPEND; - for_writing = 1; - flags |= FILEOBJ_WRITE; - break; - case OPENFILE_WRITE: - oflags = O_NONBLOCK | O_WRONLY | O_NOCTTY; - flags |= FILEOBJ_WRITE; - for_writing = 1; - break; - case OPENFILE_READ_ONLY: - oflags = O_NONBLOCK | O_RDONLY | O_NOCTTY; - flags |= FILEOBJ_READ; - for_writing = 0; - break; - case OPENFILE_READ_WRITE: - oflags = O_NONBLOCK | O_RDWR | O_NOCTTY; - flags |= FILEOBJ_READ | FILEOBJ_WRITE; - for_writing = 1; - break; - default: - fprintf(stderr, "openFile: unknown mode `%d'\n", how); - exit(EXIT_FAILURE); - } - -#if HAVE_O_BINARY - if (binary) { - oflags |= O_BINARY; - flags |= FILEOBJ_BINARY; - } -#endif - - /* First try to open without creating */ - while ((fd = open(file, oflags, 0666)) < 0) { - if (errno == ENOENT) { - if ( how == OPENFILE_READ_ONLY ) { - /* For ReadMode, just bail out now */ - ghc_errtype = ERR_NOSUCHTHING; - ghc_errstr = "file does not exist"; - return NULL; - } else { - /* If it is a dangling symlink, break off now, too. */ -#ifndef mingw32_TARGET_OS - struct stat st; - if ( lstat(file,&st) == 0) { - ghc_errtype = ERR_NOSUCHTHING; - ghc_errstr = "dangling symlink"; - return NULL; - } -#endif - } - /* Now try to create it */ - while ((fd = open(file, oflags | O_CREAT | O_EXCL, 0666)) < 0) { - if (errno == EEXIST) { - /* Race detected; go back and open without creating it */ - break; - } else if (errno != EINTR) { - cvtErrno(); - switch (ghc_errno) { - default: - stdErrno(); - break; - case GHC_ENOENT: - case GHC_ENOTDIR: - ghc_errtype = ERR_NOSUCHTHING; - ghc_errstr = "no path to file"; - break; - case GHC_EINVAL: - ghc_errtype = ERR_PERMISSIONDENIED; - ghc_errstr = "unsupported owner or group"; - break; - } - return NULL; - } - } - if (fd >= 0) { - created = 1; - break; - } - } else if (errno != EINTR) { - cvtErrno(); - switch (ghc_errno) { - default: - stdErrno(); - break; - case GHC_ENOTDIR: - ghc_errtype = ERR_NOSUCHTHING; - ghc_errstr = "no path to file"; - break; - case GHC_EINVAL: - ghc_errtype = ERR_PERMISSIONDENIED; - ghc_errstr = "unsupported owner or group"; - break; - } - return NULL; - } - } - - /* Make sure that we aren't looking at a directory */ - - while (fstat(fd, &sb) < 0) { - /* highly unlikely */ - if (errno != EINTR) { - cvtErrno(); - if (created) - (void) unlink(file); - (void) close(fd); - return NULL; - } - } - if (S_ISDIR(sb.st_mode)) { - ghc_errtype = ERR_INAPPROPRIATETYPE; - ghc_errstr = "file is a directory"; - /* We can't have created it in this case. */ - (void) close(fd); - - return NULL; - } - /* Use our own personal locking */ - - if (lockFile(fd, for_writing, 1/*enforce single-writer, if needs be.*/) < 0) { - cvtErrno(); - switch (ghc_errno) { - default: - stdErrno(); - break; - case GHC_EACCES: - case GHC_EAGAIN: - ghc_errtype = ERR_RESOURCEBUSY; - ghc_errstr = "file is locked"; - break; - } - if (created) - (void) unlink(file); - (void) close(fd); - return NULL; - } - - /* - * Write mode is supposed to truncate the file. Unfortunately, our pal - * ftruncate() is non-POSIX, so we truncate with a second open, which may fail. - */ - - if ( how == OPENFILE_WRITE ) { - int fd2, oflags2; - - oflags2 = oflags | O_TRUNC; - while ((fd2 = open(file, oflags2, 0666)) < 0) { - if (errno != EINTR) { - cvtErrno(); - if (created) - (void) unlink(file); - (void) close(fd); - switch (ghc_errno) { - default: - stdErrno(); - break; - case GHC_EAGAIN: - ghc_errtype = ERR_RESOURCEBUSY; - ghc_errstr = "enforced lock prevents truncation"; - break; - case GHC_ENOTDIR: - ghc_errtype = ERR_NOSUCHTHING; - ghc_errstr = "no path to file"; - break; - case GHC_EINVAL: - ghc_errtype = ERR_PERMISSIONDENIED; - ghc_errstr = "unsupported owner or group"; - break; - } - return NULL; - } - } - close(fd2); - } - - /* Allocate a IOFileObject to hold the information - we need to record per-handle for the various C stubs. - This chunk of memory is wrapped up inside a foreign object, - so it will be finalised and freed properly when we're - through with the handle. - */ - if ((fo = malloc(sizeof(IOFileObject))) == NULL) - return NULL; - - fo->fd = fd; - fo->buf = NULL; - fo->bufWPtr = 0; - fo->bufRPtr = 0; - fo->flags = flags; - fo->connectedTo = NULL; - return fo; -} - -/* `Lock' file descriptor and return file object. */ -IOFileObject* -openFd(StgInt fd, StgInt oflags, StgInt flags) -{ - int for_writing; - IOFileObject* fo; - - for_writing = ( ((oflags & O_WRONLY) || (oflags & O_RDWR)) ? 1 : 0); - - if (lockFile(fd, for_writing, 1/* enforce single-writer */ ) < 0) { - cvtErrno(); - switch (ghc_errno) { - default: - stdErrno(); - break; - case GHC_EACCES: - case GHC_EAGAIN: - ghc_errtype = ERR_RESOURCEBUSY; - ghc_errstr = "file is locked"; - break; - } - return NULL; - } - - /* See openFileObject() comment */ - if ((fo = malloc(sizeof(IOFileObject))) == NULL) - return NULL; - fo->fd = fd; - fo->buf = NULL; - fo->bufWPtr = 0; - fo->bufRPtr = 0; - fo->flags = flags | ( oflags & O_RDONLY ? FILEOBJ_READ - : oflags & O_RDWR ? FILEOBJ_READ - : 0) - | ( oflags & O_WRONLY ? FILEOBJ_WRITE - : oflags & O_RDWR ? FILEOBJ_WRITE - : 0); - fo->connectedTo = NULL; - return fo; -} |