diff options
author | simonm <unknown> | 1998-02-02 17:35:59 +0000 |
---|---|---|
committer | simonm <unknown> | 1998-02-02 17:35:59 +0000 |
commit | 28139aea50376444d56f43f0914291348a51a7e7 (patch) | |
tree | 595c378188638ef16462972c1e7fcdb8409c7f16 /ghc/lib/std/cbits/openFile.lc | |
parent | 98a1ebecb6d22d793b1d9f8e1d24ecbb5a2d130f (diff) | |
download | haskell-28139aea50376444d56f43f0914291348a51a7e7.tar.gz |
[project @ 1998-02-02 17:27:26 by simonm]
Library re-organisation:
All libraries now live under ghc/lib, which has the following structure:
ghc/lib/std -- all prelude files (libHS.a)
ghc/lib/std/cbits
ghc/lib/exts -- standard Hugs/GHC extensions (libHSexts.a)
-- available with '-fglasgow-exts'
ghc/lib/posix -- POSIX library (libHSposix.a)
ghc/lib/posix/cbits -- available with '-syslib posix'
ghc/lib/misc -- used to be hslibs/ghc (libHSmisc.a)
ghc/lib/misc/cbits -- available with '-syslib misc'
ghc/lib/concurrent -- Concurrent libraries (libHSconc.a)
-- available with '-concurrent'
Also, several non-standard prelude modules had their names changed to begin
with 'Prel' to reduce namespace pollution.
Addr ==> PrelAddr (Addr interface available in 'exts')
ArrBase ==> PrelArr
CCall ==> PrelCCall (CCall interface available in 'exts')
ConcBase ==> PrelConc
GHCerr ==> PrelErr
Foreign ==> PrelForeign (Foreign interface available in 'exts')
GHC ==> PrelGHC
IOHandle ==> PrelHandle
IOBase ==> PrelIOBase
GHCmain ==> PrelMain
STBase ==> PrelST
Unsafe ==> PrelUnsafe
UnsafeST ==> PrelUnsafeST
Diffstat (limited to 'ghc/lib/std/cbits/openFile.lc')
-rw-r--r-- | ghc/lib/std/cbits/openFile.lc | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/ghc/lib/std/cbits/openFile.lc b/ghc/lib/std/cbits/openFile.lc new file mode 100644 index 0000000000..4b92aca8b5 --- /dev/null +++ b/ghc/lib/std/cbits/openFile.lc @@ -0,0 +1,217 @@ +% +% (c) The GRASP/AQUA Project, Glasgow University, 1994 +% +\subsection[openFile.lc]{openFile Runtime Support} + +\begin{code} + +#include "rtsdefs.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 + +StgAddr +openFile(file, how) +StgByteArray file; +StgByteArray how; +{ + FILE *fp; + int fd; + int oflags; + int exclusive; + int created = 0; + struct stat sb; + + /* + * Since we aren't supposed to succeed when we're opening for writing and + * there's another writer, we can't just do an fopen() for "w" mode. + */ + + switch (how[0]) { + case 'a': + oflags = O_WRONLY | O_NOCTTY | O_APPEND; + exclusive = 1; + break; + case 'w': + oflags = O_WRONLY | O_NOCTTY; + exclusive = 1; + break; + case 'r': + oflags = how[1] == '+' ? O_RDWR | O_NOCTTY : O_RDONLY | O_NOCTTY; + exclusive = 0; + break; + default: + fprintf(stderr, "openFile: unknown mode `%s'\n", how); + EXIT(EXIT_FAILURE); + } + + /* First try to open without creating */ + while ((fd = open(file, oflags, 0666)) < 0) { + if (errno == ENOENT) { + if (how[0] == 'r' && how[1] == '\0') { + /* 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. */ + struct stat st; + if ( lstat(file,&st) == 0) { + ghc_errtype = ERR_NOSUCHTHING; + ghc_errstr = "dangling symlink"; + return NULL; + } + } + /* 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, exclusive) < 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[0] == 'w') { + int fd2; + + oflags |= O_TRUNC; + while ((fd2 = open(file, oflags, 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); + } + errno = 0; /* Just in case fdopen() is lame */ + while ((fp = fdopen(fd, how)) == NULL) { + if (errno != EINTR) { + cvtErrno(); + if (created) + (void) unlink(file); + (void) close(fd); + return NULL; + } + } + + return (StgAddr) fp; +} + +\end{code} |