Blob


1 #define _GNU_SOURCE /* for Linux O_DIRECT */
2 #include <u.h>
3 #define NOPLAN9DEFINES
4 #include <sys/file.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <libc.h>
8 #include <sys/stat.h>
9 #ifndef O_DIRECT
10 #define O_DIRECT 0
11 #endif
13 int
14 p9create(char *path, int mode, ulong perm)
15 {
16 int fd, cexec, umode, rclose, lock, rdwr;
17 struct flock fl;
19 rdwr = mode&3;
20 lock = mode&OLOCK;
21 cexec = mode&OCEXEC;
22 rclose = mode&ORCLOSE;
23 mode &= ~(ORCLOSE|OCEXEC|OLOCK);
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);
38 if(mode&ODIRECT){
39 umode |= O_DIRECT;
40 mode &= ~ODIRECT;
41 }
42 if(mode&OEXCL){
43 umode |= O_EXCL;
44 mode &= ~OEXCL;
45 }
46 if(mode&OAPPEND){
47 umode |= O_APPEND;
48 mode &= ~OAPPEND;
49 }
50 if(mode){
51 werrstr("unsupported mode in create");
52 goto out;
53 }
54 fd = open(path, umode, perm);
55 }
56 out:
57 if(fd >= 0){
58 if(lock){
59 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){
64 close(fd);
65 werrstr("lock: %r");
66 return -1;
67 }
68 }
69 if(cexec)
70 fcntl(fd, F_SETFL, FD_CLOEXEC);
71 if(rclose)
72 remove(path);
73 }
74 return fd;
75 }