9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | 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 }