2 * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
4 * $Id: openFile.c,v 1.4 1999/01/07 15:48:40 simonm Exp $
6 * openFile Runtime Support
9 /* We use lstat, which is sadly not POSIX */
10 #define NON_POSIX_SOURCE
14 #include "fileObject.h"
16 #ifdef HAVE_SYS_TYPES_H
17 #include <sys/types.h>
20 #ifdef HAVE_SYS_STAT_H
33 openStdFile(fd,flags,rd)
40 if ((fo = malloc(sizeof(IOFileObject))) == NULL)
46 fo->flags = flags | FILEOBJ_STD | ( rd ? FILEOBJ_READ : FILEOBJ_WRITE);
47 fo->connectedTo = NULL;
51 #define OPENFILE_APPEND 0
52 #define OPENFILE_WRITE 1
53 #define OPENFILE_READ_ONLY 2
54 #define OPENFILE_READ_WRITE 3
57 openFile(file, how, binary, flags)
71 #ifdef __CONCURRENT_HASKELL__
72 #warning FixMe: Ignoring bogus bit 7 in openFiles 2nd argument
77 * Since we aren't supposed to succeed when we're opening for writing and
78 * there's another writer, we can't just do an open() with O_WRONLY.
83 oflags = O_WRONLY | O_NOCTTY | O_APPEND;
87 oflags = O_WRONLY | O_NOCTTY;
90 case OPENFILE_READ_ONLY:
91 oflags = O_RDONLY | O_NOCTTY;
94 case OPENFILE_READ_WRITE:
95 oflags = O_RDWR | O_NOCTTY;
99 fprintf(stderr, "openFile: unknown mode `%d'\n", how);
108 /* First try to open without creating */
109 while ((fd = open(file, oflags, 0666)) < 0) {
110 if (errno == ENOENT) {
111 if ( how == OPENFILE_READ_ONLY ) {
112 /* For ReadMode, just bail out now */
113 ghc_errtype = ERR_NOSUCHTHING;
114 ghc_errstr = "file does not exist";
117 /* If it is a dangling symlink, break off now, too. */
119 if ( lstat(file,&st) == 0) {
120 ghc_errtype = ERR_NOSUCHTHING;
121 ghc_errstr = "dangling symlink";
125 /* Now try to create it */
126 while ((fd = open(file, oflags | O_CREAT | O_EXCL, 0666)) < 0) {
127 if (errno == EEXIST) {
128 /* Race detected; go back and open without creating it */
130 } else if (errno != EINTR) {
138 ghc_errtype = ERR_NOSUCHTHING;
139 ghc_errstr = "no path to file";
142 ghc_errtype = ERR_PERMISSIONDENIED;
143 ghc_errstr = "unsupported owner or group";
153 } else if (errno != EINTR) {
160 ghc_errtype = ERR_NOSUCHTHING;
161 ghc_errstr = "no path to file";
164 ghc_errtype = ERR_PERMISSIONDENIED;
165 ghc_errstr = "unsupported owner or group";
172 /* Make sure that we aren't looking at a directory */
174 while (fstat(fd, &sb) < 0) {
175 /* highly unlikely */
176 if (errno != EINTR) {
184 if (S_ISDIR(sb.st_mode)) {
185 ghc_errtype = ERR_INAPPROPRIATETYPE;
186 ghc_errstr = "file is a directory";
187 /* We can't have created it in this case. */
192 /* Use our own personal locking */
194 if (lockFile(fd, exclusive) < 0) {
202 ghc_errtype = ERR_RESOURCEBUSY;
203 ghc_errstr = "file is locked";
213 * Write mode is supposed to truncate the file. Unfortunately, our pal
214 * ftruncate() is non-POSIX, so we truncate with a second open, which may fail.
217 if ( how == OPENFILE_WRITE ) {
220 oflags2 = oflags | O_TRUNC;
221 while ((fd2 = open(file, oflags2, 0666)) < 0) {
222 if (errno != EINTR) {
232 ghc_errtype = ERR_RESOURCEBUSY;
233 ghc_errstr = "enforced lock prevents truncation";
236 ghc_errtype = ERR_NOSUCHTHING;
237 ghc_errstr = "no path to file";
240 ghc_errtype = ERR_PERMISSIONDENIED;
241 ghc_errstr = "unsupported owner or group";
250 /* Allocate a IOFileObject to hold the information
251 we need to record per-handle for the various C stubs.
252 This chunk of memory is wrapped up inside a foreign object,
253 so it will be finalised and freed properly when we're
254 through with the handle.
256 if ((fo = malloc(sizeof(IOFileObject))) == NULL)
263 fo->flags = flags | ( (how == OPENFILE_READ_ONLY || how == OPENFILE_READ_WRITE) ? FILEOBJ_READ : 0)
264 | ( (how == OPENFILE_APPEND || how == OPENFILE_READ_WRITE) ? FILEOBJ_WRITE : 0);
265 fo->connectedTo = NULL;
269 /* `Lock' file descriptor and return file object. */
271 openFd(fd,oflags,flags)
280 if (lockFile(fd, exclusive) < 0) {
288 ghc_errtype = ERR_RESOURCEBUSY;
289 ghc_errstr = "file is locked";
295 /* See openFileObject() comment */
296 if ((fo = malloc(sizeof(IOFileObject))) == NULL)
302 fo->flags = flags | ( oflags & O_RDONLY ? FILEOBJ_READ
303 : oflags & O_RDWR ? FILEOBJ_READ
305 | ( oflags & O_WRONLY ? FILEOBJ_WRITE
306 : oflags & O_RDWR ? FILEOBJ_WRITE
308 fo->connectedTo = NULL;