blob: e4e3c715e963ee843bcbb0a6c03f09fd41f52ebe [file] [log] [blame]
rscbe36ff62004-04-29 17:13:24 +00001#define _GNU_SOURCE /* for Linux O_DIRECT */
rscfd04aac2003-11-23 18:12:54 +00002#include <u.h>
rsc32f69c32003-12-11 17:48:38 +00003#define NOPLAN9DEFINES
rsce7504002004-06-11 14:38:56 +00004#include <sys/file.h>
rscf84eebe2005-01-04 22:18:40 +00005#include <unistd.h>
6#include <fcntl.h>
rscfd04aac2003-11-23 18:12:54 +00007#include <libc.h>
rsc32f69c32003-12-11 17:48:38 +00008#include <sys/stat.h>
rsc983990c2004-05-14 20:19:53 +00009#ifndef O_DIRECT
10#define O_DIRECT 0
11#endif
rsc32f69c32003-12-11 17:48:38 +000012
rscfd04aac2003-11-23 18:12:54 +000013int
rsc8ad51792004-03-25 23:03:57 +000014p9create(char *path, int mode, ulong perm)
rscfd04aac2003-11-23 18:12:54 +000015{
rscd9e16d22004-06-11 18:57:32 +000016 int fd, cexec, umode, rclose, lock, rdwr;
rscf84eebe2005-01-04 22:18:40 +000017 struct flock fl;
rsc32f69c32003-12-11 17:48:38 +000018
rscd9e16d22004-06-11 18:57:32 +000019 rdwr = mode&3;
rsce7504002004-06-11 14:38:56 +000020 lock = mode&OLOCK;
rsc32f69c32003-12-11 17:48:38 +000021 cexec = mode&OCEXEC;
22 rclose = mode&ORCLOSE;
rsce7504002004-06-11 14:38:56 +000023 mode &= ~(ORCLOSE|OCEXEC|OLOCK);
rsc32f69c32003-12-11 17:48:38 +000024
25 /* XXX should get mode mask right? */
26 fd = -1;
27 if(perm&DMDIR){
28 if(mode != OREAD){
29 werrstr("bad mode in directory create");
30 goto out;
31 }
32 if(mkdir(path, perm&0777) < 0)
33 goto out;
34 fd = open(path, O_RDONLY);
35 }else{
36 umode = (mode&3)|O_CREAT|O_TRUNC;
37 mode &= ~(3|OTRUNC);
rscbe36ff62004-04-29 17:13:24 +000038 if(mode&ODIRECT){
39 umode |= O_DIRECT;
40 mode &= ~ODIRECT;
41 }
rsc32f69c32003-12-11 17:48:38 +000042 if(mode&OEXCL){
43 umode |= O_EXCL;
44 mode &= ~OEXCL;
45 }
rscb589fce2005-02-11 16:58:23 +000046 if(mode&OAPPEND){
47 umode |= O_APPEND;
48 mode &= ~OAPPEND;
49 }
rsc32f69c32003-12-11 17:48:38 +000050 if(mode){
51 werrstr("unsupported mode in create");
52 goto out;
53 }
54 fd = open(path, umode, perm);
55 }
56out:
57 if(fd >= 0){
rsce7504002004-06-11 14:38:56 +000058 if(lock){
rscf84eebe2005-01-04 22:18:40 +000059 fl.l_type = (rdwr==OREAD) ? F_RDLCK : F_WRLCK;
60 fl.l_whence = SEEK_SET;
61 fl.l_start = 0;
62 fl.l_len = 0;
63 if(fcntl(fd, F_SETLK, &fl) < 0){
rsce7504002004-06-11 14:38:56 +000064 close(fd);
rsc915734a2005-03-18 19:03:45 +000065 werrstr("lock: %r");
rsce7504002004-06-11 14:38:56 +000066 return -1;
67 }
68 }
rsc32f69c32003-12-11 17:48:38 +000069 if(cexec)
70 fcntl(fd, F_SETFL, FD_CLOEXEC);
71 if(rclose)
72 remove(path);
73 }
rsc32f69c32003-12-11 17:48:38 +000074 return fd;
rscfd04aac2003-11-23 18:12:54 +000075}