create.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       create.c (1385B)
       ---
            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
           12 
           13 int
           14 p9create(char *path, int mode, ulong perm)
           15 {
           16         int fd, cexec, umode, rclose, lock, rdwr;
           17         struct flock fl;
           18 
           19         rdwr = mode&3;
           20         lock = mode&OLOCK;
           21         cexec = mode&OCEXEC;
           22         rclose = mode&ORCLOSE;
           23         mode &= ~(ORCLOSE|OCEXEC|OLOCK);
           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);
           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 }