75 lines · 1.4 KB · C
RawDownload
#define _GNU_SOURCE	/* for Linux O_DIRECT */#include <u.h>#define NOPLAN9DEFINES#include <sys/file.h>#include <unistd.h>#include <fcntl.h>#include <libc.h>#include <sys/stat.h>#ifndef O_DIRECT#define O_DIRECT 0#endif intp9create(char *path, int mode, ulong perm){	int fd, cexec, umode, rclose, lock, rdwr;	struct flock fl; 	rdwr = mode&3;	lock = mode&OLOCK;	cexec = mode&OCEXEC;	rclose = mode&ORCLOSE;	mode &= ~(ORCLOSE|OCEXEC|OLOCK); 	/* XXX should get mode mask right? */	fd = -1;	if(perm&DMDIR){		if(mode != OREAD){			werrstr("bad mode in directory create");			goto out;		}		if(mkdir(path, perm&0777) < 0)			goto out;		fd = open(path, O_RDONLY);	}else{		umode = (mode&3)|O_CREAT|O_TRUNC;		mode &= ~(3|OTRUNC);		if(mode&ODIRECT){			umode |= O_DIRECT;			mode &= ~ODIRECT;		}		if(mode&OEXCL){			umode |= O_EXCL;			mode &= ~OEXCL;		}		if(mode&OAPPEND){			umode |= O_APPEND;			mode &= ~OAPPEND;		}		if(mode){			werrstr("unsupported mode in create");			goto out;		}		fd = open(path, umode, perm);	}out:	if(fd >= 0){		if(lock){			fl.l_type = (rdwr==OREAD) ? F_RDLCK : F_WRLCK;			fl.l_whence = SEEK_SET;			fl.l_start = 0;			fl.l_len = 0;			if(fcntl(fd, F_SETLK, &fl) < 0){				close(fd);				werrstr("lock: %r");				return -1;			}		}		if(cexec)			fcntl(fd, F_SETFL, FD_CLOEXEC);		if(rclose)			remove(path);	}	return fd;}