rsc | be36ff6 | 2004-04-29 17:13:24 +0000 | [diff] [blame] | 1 | #define _GNU_SOURCE /* for Linux O_DIRECT */ |
rsc | fd04aac | 2003-11-23 18:12:54 +0000 | [diff] [blame] | 2 | #include <u.h> |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 3 | #define NOPLAN9DEFINES |
rsc | e750400 | 2004-06-11 14:38:56 +0000 | [diff] [blame] | 4 | #include <sys/file.h> |
rsc | f84eebe | 2005-01-04 22:18:40 +0000 | [diff] [blame] | 5 | #include <unistd.h> |
| 6 | #include <fcntl.h> |
rsc | fd04aac | 2003-11-23 18:12:54 +0000 | [diff] [blame] | 7 | #include <libc.h> |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 8 | #include <sys/stat.h> |
rsc | 983990c | 2004-05-14 20:19:53 +0000 | [diff] [blame] | 9 | #ifndef O_DIRECT |
| 10 | #define O_DIRECT 0 |
| 11 | #endif |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 12 | |
rsc | fd04aac | 2003-11-23 18:12:54 +0000 | [diff] [blame] | 13 | int |
rsc | 8ad5179 | 2004-03-25 23:03:57 +0000 | [diff] [blame] | 14 | p9create(char *path, int mode, ulong perm) |
rsc | fd04aac | 2003-11-23 18:12:54 +0000 | [diff] [blame] | 15 | { |
rsc | d9e16d2 | 2004-06-11 18:57:32 +0000 | [diff] [blame] | 16 | int fd, cexec, umode, rclose, lock, rdwr; |
rsc | f84eebe | 2005-01-04 22:18:40 +0000 | [diff] [blame] | 17 | struct flock fl; |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 18 | |
rsc | d9e16d2 | 2004-06-11 18:57:32 +0000 | [diff] [blame] | 19 | rdwr = mode&3; |
rsc | e750400 | 2004-06-11 14:38:56 +0000 | [diff] [blame] | 20 | lock = mode&OLOCK; |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 21 | cexec = mode&OCEXEC; |
| 22 | rclose = mode&ORCLOSE; |
rsc | e750400 | 2004-06-11 14:38:56 +0000 | [diff] [blame] | 23 | mode &= ~(ORCLOSE|OCEXEC|OLOCK); |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 24 | |
| 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); |
rsc | be36ff6 | 2004-04-29 17:13:24 +0000 | [diff] [blame] | 38 | if(mode&ODIRECT){ |
| 39 | umode |= O_DIRECT; |
| 40 | mode &= ~ODIRECT; |
| 41 | } |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 42 | if(mode&OEXCL){ |
| 43 | umode |= O_EXCL; |
| 44 | mode &= ~OEXCL; |
| 45 | } |
rsc | b589fce | 2005-02-11 16:58:23 +0000 | [diff] [blame^] | 46 | if(mode&OAPPEND){ |
| 47 | umode |= O_APPEND; |
| 48 | mode &= ~OAPPEND; |
| 49 | } |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 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){ |
rsc | e750400 | 2004-06-11 14:38:56 +0000 | [diff] [blame] | 58 | if(lock){ |
rsc | f84eebe | 2005-01-04 22:18:40 +0000 | [diff] [blame] | 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){ |
rsc | e750400 | 2004-06-11 14:38:56 +0000 | [diff] [blame] | 64 | close(fd); |
| 65 | return -1; |
| 66 | } |
| 67 | } |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 68 | if(cexec) |
| 69 | fcntl(fd, F_SETFL, FD_CLOEXEC); |
| 70 | if(rclose) |
| 71 | remove(path); |
| 72 | } |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 73 | return fd; |
rsc | fd04aac | 2003-11-23 18:12:54 +0000 | [diff] [blame] | 74 | } |