kernel&all: create() syscall only sends Tcreate

In Plan9 the create syscall fallback on a open(OTRUNC) if the
path provided already exists. This is actually a common requirement
as most programs (editors, cat...) simply requires that a file is
there and is empty, and doesn't care overwriting existing contents
(note that this is particularily sensible with something like fossil).

In Jehanne the application is responsible of actually handle this
"file exists" error but libc provides ocreate() to mimic the Plan9
behaviour. Note that ocreate introduce a subtle race too: the path
is walked several times if the file exists, thus it could misbehave
on concurrent namespace changes. However I guess this is not going to
happen often enough to care now.

NOTE we will probably address this rare race too, with a more drammatic change
to syscalls: a new walk() syscall that will provide an unopen fd.
This commit is contained in:
2016-12-24 21:25:20 +01:00
parent 0c094289e6
commit b862596737
78 changed files with 271 additions and 289 deletions

View File

@ -28,7 +28,7 @@ main(void)
static Rune r[16] = L"Ciao Mondo!";
static Rune buf[16];
if((fd = create("/tmp/runetest.txt", OWRITE, 0666L)) < 0) {
if((fd = ocreate("/tmp/runetest.txt", OWRITE, 0666L)) < 0) {
print("FAIL: open: %r\n");
exits("FAIL");
}

View File

@ -16,7 +16,7 @@ fdfork(int fd, int post)
pipe(ch);
len = snprint(path, sizeof path, "hcube.%d.%d", getpid(), seq++);
pfd = create(path, OWRITE|ORCLOSE, 0666);
pfd = ocreate(path, OWRITE|ORCLOSE, 0666);
if(pfd == -1)
sysfatal("fdfork: create: %r");
snprint(buf, sizeof buf, "%d", ch[0]);

View File

@ -20,10 +20,11 @@
#define NP_ORDWR 2 /* read and write */
#define NP_OEXEC 3 /* execute, == read but check execute permission */
#define NP_OTRUNC 16 /* or'ed in (except for exec), truncate file first */
#define NP_OCEXEC 32 /* or'ed in, close on exec */
#define NP_ORCLOSE 64 /* or'ed in, remove on close */
/* bits that must be zero in open/create mode */
#define NP_OZEROES ~(NP_OREAD|NP_OWRITE|NP_ORDWR|NP_OEXEC|NP_OTRUNC|NP_ORCLOSE)
#define NP_OZEROES ~(NP_OREAD|NP_OWRITE|NP_ORDWR|NP_OEXEC|NP_OTRUNC|NP_OCEXEC|NP_ORCLOSE)
typedef enum NinepMsgType
{

View File

@ -396,6 +396,7 @@ extern void longjmp(jmp_buf, int);
extern char* mktemp(char*);
extern double modf(double, double*);
extern void notejmp(void*, jmp_buf, int);
extern int ocreate(const char* path, unsigned int omode, unsigned int perm);
extern void perror(const char*);
extern int pipe(int pipes[2]);
extern int postnote(int, int, const char *);
@ -565,14 +566,12 @@ extern void freenetconninfo(NetConnInfo*);
/* Open modes: Popular flags among filesystems */
#define OTRUNC 0x0100 /* or'ed in (except for exec), truncate file first */
#define OEXCL 0x0200 /* or'ed in, exclusive create */
/* Access modes */
#define AEXIST OSTAT /* accessible: exists */
#define AREAD OREAD /* read access */
#define AWRITE OWRITE /* write access */
#define AEXEC OEXEC /* execute access */
#define AMASK (OSTAT|OREAD|OWRITE|OEXEC)
#define AEXIST 0 /* accessible: exists */
#define AREAD 4 /* read access */
#define AWRITE 2 /* write access */
#define AEXEC 1 /* execute access */
/* Segattch */
#define SG_RONLY 0040 /* read only */
@ -654,58 +653,23 @@ struct Waitmsg
char *msg;
} Waitmsg;
//extern void _exits(const char*) __attribute__ ((noreturn));
extern int access(const char*, int);
//extern int64_t alarm(uint64_t);
//extern int await(char*, int);
//extern int64_t awake(int64_t);
extern int awakened(int64_t);
//extern int bind(const char*, const char*, int);
extern int brk(void*);
//extern int chdir(const char*);
//extern int close(int);
//extern int create(const char*, int, uint32_t);
//extern int dup(int, int);
//extern int errstr(char*, uint32_t);
//extern int exec(const char*, char* const[]);
extern int execl(const char*, ...);
extern int forgivewkp(int64_t);
extern pid_t fork(void);
//extern pid_t rfork(int);
//extern int fauth(int, const char*);
//extern int fstat(int, uint8_t*, int);
//extern int fwstat(int, uint8_t*, int);
//extern int fversion(int, int, char*, int);
//extern int mount(int, int, const char*, int, const char*, int);
//extern int unmount(const char*, const char*);
//extern int noted(int);
//extern int notify(void(*)(void*, char*));
//extern int open(const char*, int);
//extern int fd2path(int, char*, int);
// extern int fdflush(int);
//extern int pipe(int*);
//extern int32_t pread(int, void*, int32_t, int64_t);
//extern int32_t pwrite(int, const void*, int32_t, int64_t);
//extern int32_t read(int, void*, int32_t);
extern int32_t readn(int, void*, int32_t);
//extern int remove(const char*);
extern void* sbrk(uint32_t);
extern int32_t oseek(int, int32_t, int);
//extern int64_t seek(int, int64_t, int);
extern void* segattach(int, const char*, void*, unsigned long);
extern int segdetach(void*);
extern int segfree(void*, unsigned long);
//extern int semacquire(int32_t*, int);
//extern int32_t semrelease(int32_t*, int32_t);
extern void sleep(int32_t);
extern int stat(const char*, uint8_t*, int);
//extern int tsemacquire(int32_t*, uint64_t);
extern Waitmsg* wait(void);
extern int waitpid(void);
//extern int32_t write(int, const void*, int32_t);
extern int wstat(const char*, uint8_t*, int);
//extern void* rendezvous(void*, void*);
extern Dir* dirstat(const char*);
extern Dir* dirfstat(int);

View File

@ -334,10 +334,10 @@ acmeerrorinit(void)
if(pipe(pfd) < 0)
error("can't create pipe");
sprint(acmeerrorfile, "/srv/acme.%s.%d", getuser(), mainpid);
fd = create(acmeerrorfile, OWRITE, 0666);
fd = ocreate(acmeerrorfile, OWRITE, 0666);
if(fd < 0){
remove(acmeerrorfile);
fd = create(acmeerrorfile, OWRITE, 0666);
fd = ocreate(acmeerrorfile, OWRITE, 0666);
if(fd < 0)
error("can't create acmeerror file");
}

View File

@ -33,7 +33,7 @@ tempfile(void)
buf[5] = i;
if(access(buf, AEXIST) == 0)
continue;
fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
fd = ocreate(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
if(fd >= 0)
return fd;
}

View File

@ -594,7 +594,7 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname)
goto Rescue1;
}
}
fd = create(name, OWRITE, 0666);
fd = ocreate(name, OWRITE, 0666);
if(fd < 0){
warning(nil, "can't create file %s: %r\n", name);
goto Rescue1;
@ -1379,7 +1379,7 @@ Hard:
n += i;
memmove(buf+n, "/cmd", 5);
n += 5;
fd = create("/env/path", OWRITE, 0666);
fd = ocreate("/env/path", OWRITE, 0666);
write(fd, buf, n);
close(fd);
}

View File

@ -548,7 +548,7 @@ fsysopen(Xfid *x, Fid *f)
int m;
/* can't truncate anything, so just disregard */
x->mode &= ~(NP_OTRUNC);
x->mode &= ~(NP_OTRUNC|NP_OCEXEC);
/* can't execute or remove anything */
if(x->mode==NP_OEXEC || (x->mode&NP_ORCLOSE))
goto Deny;

View File

@ -322,7 +322,7 @@ rowdump(Row *row, char *file)
sprint(buf, "%s/acme.dump", home);
file = buf;
}
fd = create(file, OWRITE, 0600);
fd = ocreate(file, OWRITE, 0600);
if(fd < 0){
warning(nil, "can't open %s: %r\n", file);
goto Rescue;
@ -666,7 +666,7 @@ rowload(Row *row, char *file, int initing)
if(ndumped >= 0){
/* simplest thing is to put it in a file and load that */
sprint(buf, "/tmp/d%d.%.4sacme", getpid(), getuser());
fd = create(buf, OWRITE|ORCLOSE, 0600);
fd = ocreate(buf, OWRITE|ORCLOSE, 0600);
if(fd < 0){
free(r);
warning(nil, "can't create temp file: %r\n");

View File

@ -117,7 +117,7 @@ fatal(char *fmt, ...)
static int
openlock(char *file)
{
return create(file, ORDWR, 0600);
return ocreate(file, ORDWR, 0600);
}
static int
@ -258,7 +258,7 @@ createuser(void)
dirfwstat(fd, &d);
close(fd);
snprint(file, sizeof file, "/cron/%s/cron", user);
fd = create(file, OREAD, 0644);
fd = ocreate(file, OREAD, 0644);
if(fd < 0)
fatal("couldn't create %s: %r", file);
nulldir(&d);

View File

@ -770,7 +770,7 @@ writeusers(void)
}
/* write file */
fd = create(userkeys, OWRITE, 0660);
fd = ocreate(userkeys, OWRITE, 0660);
if(fd < 0){
free(buf);
fprint(2, "keyfs: can't write keys file\n");

View File

@ -13,7 +13,7 @@ wrbio(char *file, Acctbio *a)
fd = open(file, OWRITE);
if(fd < 0){
fd = create(file, OWRITE, 0660);
fd = ocreate(file, OWRITE, 0660);
if(fd < 0)
error("can't create %s", file);
}

View File

@ -71,7 +71,7 @@ setenv(char *var, char *val)
{
int fd;
fd = create(var, OWRITE, 0644);
fd = ocreate(var, OWRITE, 0644);
if(fd < 0)
print("init: can't open %s\n", var);
else{

View File

@ -86,7 +86,7 @@ getfile(SConn *conn, char *gf, uint8_t **buf, uint32_t *buflen, uint8_t *key, in
* conn is already encrypted against wiretappers, but gf is also
* encrypted against server breakin.
*/
if(buf == nil && (fd = create(gf, OWRITE, 0600)) < 0){
if(buf == nil && (fd = ocreate(gf, OWRITE, 0600)) < 0){
fprint(2, "secstore: can't open %s: %r\n", gf);
return -1;
}

View File

@ -142,7 +142,7 @@ putfile(SConn *conn, char *id, char *pf)
}
snprint(s, Maxmsg, "%s/store/%s/%s", SECSTORE_DIR, id, pf);
pd = create(s, OWRITE, 0660);
pd = ocreate(s, OWRITE, 0660);
if(pd < 0){
syslog(0, LOG, "can't open %s: %r", s);
return -1;

View File

@ -18,7 +18,7 @@ ensure_exists(char *f, uint32_t perm)
return;
if(verbose)
fprint(2,"first time setup for secstore: create %s %lo\n", f, perm);
fd = create(f, OREAD, perm);
fd = ocreate(f, OREAD, perm);
if(fd < 0)
sysfatal("unable to create %s: %r", f);
close(fd);

View File

@ -125,7 +125,7 @@ copy(char *from, char *to, int todir)
failed = 1;
return;
}
fdt=create(to, OWRITE, mode);
fdt=ocreate(to, OWRITE, mode);
if(fdt<0){
fprint(2, "cp: can't create %s: %r\n", to);
close(fdf);

View File

@ -216,7 +216,7 @@ main(int argc, char *argv[])
}
if(ofile){
if(dotrunc)
obf = create(ofile, OWRITE, 0664);
obf = ocreate(ofile, OWRITE, 0664);
else
obf = open(ofile, OWRITE);
if(obf < 0) {

View File

@ -262,7 +262,7 @@ main(int argc, char **argv)
disk = opendisk(argv[0], 0, 0);
if(disk == nil) {
if(fflag) {
if((fd = create(argv[0], ORDWR, 0666)) >= 0) {
if((fd = ocreate(argv[0], ORDWR, 0666)) >= 0) {
file = argv[0];
close(fd);
disk = opendisk(argv[0], 0, 0);

View File

@ -142,7 +142,7 @@ mkdirs(char *name, char *namep)
if(p[1] == '\0')
return;
*p = 0;
fd = create(buf, OREAD, 0775|DMDIR);
fd = ocreate(buf, OREAD, 0775|DMDIR);
close(fd);
*p = '/';
}
@ -156,7 +156,7 @@ mkdir(char *name, uint32_t mode, uint32_t mtime, char *uid, char *gid)
char *p;
char olderr[256];
fd = create(name, OREAD, mode);
fd = ocreate(name, OREAD, mode);
if(fd < 0){
rerrstr(olderr, sizeof(olderr));
if((d = dirstat(name)) == nil || !(d->mode & DMDIR)){

View File

@ -179,7 +179,7 @@ copy(Dir *d)
if(!p)
error("internal temporary file error");
strcpy(p+1, "__mkfstmp");
t = create(cptmp, OWRITE, 0666);
t = ocreate(cptmp, OWRITE, 0666);
if(t < 0){
warn("can't create %q: %r", newfile);
close(f);
@ -261,7 +261,7 @@ mkdir(Dir *d)
arch(d);
return;
}
fd = create(newfile, OREAD, d->mode);
fd = ocreate(newfile, OREAD, d->mode);
nulldir(&nd);
nd.mode = d->mode;
nd.gid = d->gid;

View File

@ -233,7 +233,7 @@ main(int argc, char *argv[])
sysfatal("pipe: %r");
if(srv){
snprint(buf, sizeof buf, "#s/%s", srvname);
fd = create(buf, OWRITE, 0666);
fd = ocreate(buf, OWRITE, 0666);
if(fd < 0)
sysfatal("create %s: %r", buf);
if(fprint(fd, "%d", pfd[0]) < 0)

View File

@ -106,7 +106,7 @@ main(int argc, char **argv)
open("/dev/null", OWRITE);
if(pipe(pipefd) < 0)
panic("pipe");
srvfd = create(srvfile, OWRITE|ORCLOSE, 0600);
srvfd = ocreate(srvfile, OWRITE|ORCLOSE, 0600);
if(srvfd < 0)
panic(srvfile);
fprint(srvfd, "%d", pipefd[0]);

View File

@ -382,7 +382,7 @@ commands(void)
if(!wrapp ||
((io = open(file, OWRITE)) == -1) ||
((seek(io, 0L, 2)) == -1))
if((io = create(file, OWRITE, 0666)) < 0)
if((io = ocreate(file, OWRITE, 0666)) < 0)
error(file);
Binit(&iobuf, io, OWRITE);
wrapp = 0;
@ -681,7 +681,7 @@ rescue(void)
if(dol > zero) {
addr1 = zero+1;
addr2 = dol;
io = create("ed.hup", OWRITE, 0666);
io = ocreate("ed.hup", OWRITE, 0666);
if(io > 0){
Binit(&iobuf, io, OWRITE);
putfile();
@ -1110,7 +1110,7 @@ init(void)
iblock = -1;
oblock = -1;
ichanged = 0;
if((tfile = create(tfname, ORDWR, 0600)) < 0){
if((tfile = ocreate(tfname, ORDWR, 0600)) < 0){
error1(T);
exits(0);
}

View File

@ -242,7 +242,7 @@ main(int argc, char **argv)
exclusions();
if(dbg) {
n = create(dbfile, OWRITE|OTRUNC, 0666);
n = ocreate(dbfile, OWRITE|OTRUNC, 0666);
dup(n, DFD);
close(n);
}

View File

@ -311,7 +311,7 @@ Xcreate(Fsrpc *t)
path = makepath(f->f, t->work.name);
f->fid = create(path, t->work.mode, t->work.perm);
f->fid = ocreate(path, t->work.mode, t->work.perm);
free(path);
if(f->fid < 0) {
errstr(err, sizeof err);

View File

@ -131,7 +131,7 @@ copy(char *from, char *to, int todir)
failed = 1;
return;
}
fdt=create(to, OWRITE, mode);
fdt=ocreate(to, OWRITE, mode);
if(fdt<0){
fprint(2, "fcp: can't create %s: %r\n", to);
close(fdf);

View File

@ -177,7 +177,7 @@ main(int argc, char **argv)
if(ofile != nil){
d = dirstat(ofile);
if(d == nil){
out.fd = create(ofile, OWRITE, 0664);
out.fd = ocreate(ofile, OWRITE, 0664);
if(out.fd < 0)
sysfatal("creating %s: %r", ofile);
} else {

View File

@ -398,7 +398,7 @@ initcons(char *service)
char buf[512];
snprint(buf, sizeof(buf), "/srv/%s.cmd", service);
fd = create(buf, OWRITE|ORCLOSE, 0600);
fd = ocreate(buf, OWRITE|ORCLOSE, 0600);
if(fd < 0)
return;
pipe(pfd);

View File

@ -58,7 +58,7 @@ enabledebug(const char *file)
if (!debugging) {
if((fd = open(file, OCEXEC|OTRUNC|OWRITE)) < 0){
debug("open: %r\n");
if((fd = create(file, OCEXEC|OWRITE, 0666)) < 0)
if((fd = ocreate(file, OCEXEC|OWRITE, 0666)) < 0)
sysfatal("create %r");
}
dup(fd, 2);
@ -211,9 +211,9 @@ post(char *srv, int fd)
fprint(2, "post %s...\n", srv);
sprint(buf, "#s/%s", srv);
f = create(buf, OWRITE, 0666);
f = ocreate(buf, OWRITE, 0666);
if(f < 0)
sysfatal("create(%s)", srv);
sysfatal("ocreate(%s)", srv);
sprint(buf, "%d", fd);
if(write(f, buf, strlen(buf)) != strlen(buf))
sysfatal("write");

View File

@ -357,7 +357,7 @@ moreinput(void)
expr = infile+2;
sprint(buf, "/tmp/hocXXXXXXX");
infile = mktemp(buf);
fd = create(infile, ORDWR|ORCLOSE, 0600);
fd = ocreate(infile, ORDWR|ORCLOSE, 0600);
if(fd < 0){
fprint(2, "%s: can't create temp. file: %r\n", progname);
return 0;

View File

@ -75,7 +75,7 @@ post(char *name, char *envname, int srvfd)
int fd;
char buf[32];
fd = create(name, OWRITE, 0600);
fd = ocreate(name, OWRITE, 0600);
if(fd < 0)
return;
sprint(buf, "%d",srvfd);

View File

@ -220,7 +220,7 @@ setenv(char *name, char *val)
{
int fd;
fd = create(name, OWRITE, 0644);
fd = ocreate(name, OWRITE, 0644);
if(fd < 0)
fprint(2, "init: can't create %s: %r\n", name);
else{

View File

@ -106,7 +106,7 @@ lockopen(char *file)
}
if(strstr(err, "exist")){
/* no file, create an exclusive access file */
fd = create(file, ORDWR, DMEXCL|0664);
fd = ocreate(file, ORDWR, DMEXCL|0664);
if(fd >= 0)
return fd;
}

View File

@ -1306,7 +1306,7 @@ openfreqfile(void)
}
fd = open(p, ORDWR);
if(fd < 0)
fd = create(p, ORDWR, 0666);
fd = ocreate(p, ORDWR, 0666);
free(p);
if(fd < 0)
return -1;

View File

@ -129,7 +129,7 @@ main(int argc, char *argv[])
case -1:
error("fork");
case 0:
fd = create("/env/prompt", OWRITE, 0666);
fd = ocreate("/env/prompt", OWRITE, 0666);
if (fd >= 0) {
fprint(fd, "%s%% ", lock);
close(fd);

View File

@ -150,7 +150,7 @@ mv1(char *from, Dir *dirb, char *todir, char *toelem)
hardremove(toname); /* because create() won't truncate file */
free(dirt);
fdt = create(toname, OWRITE, dirb->mode);
fdt = ocreate(toname, OWRITE, dirb->mode);
if(fdt < 0){
fprint(2, "mv: can't create %s: %r\n", toname);
close(fdf);

View File

@ -308,7 +308,7 @@ mountinit(char *service, char *mntpt)
/*
* make a /srv/cs
*/
f = create(service, OWRITE|ORCLOSE, 0666);
f = ocreate(service, OWRITE|ORCLOSE, 0666);
if(f < 0)
error(service);
snprint(buf, sizeof(buf), "%d", p[1]);

View File

@ -257,7 +257,7 @@ dnstats(char *file)
{
int i, fd;
fd = create(file, OWRITE, 0666);
fd = ocreate(file, OWRITE, 0666);
if(fd < 0)
return;
@ -301,7 +301,7 @@ dndump(char *file)
DN *dp;
RR *rp;
fd = create(file, OWRITE, 0666);
fd = ocreate(file, OWRITE, 0666);
if(fd < 0)
return;

View File

@ -267,7 +267,7 @@ mountinit(char *service, char *mntpt)
/*
* make a /srv/dns
*/
if((f = create(service, OWRITE|ORCLOSE, 0666)) < 0)
if((f = ocreate(service, OWRITE|ORCLOSE, 0666)) < 0)
sysfatal("create %s failed: %r", service);
snprint(buf, sizeof buf, "%d", p[1]);
if(write(f, buf, strlen(buf)) != strlen(buf))

View File

@ -125,7 +125,7 @@ main(int argc, char **argv)
/* create the hash file */
snprint(file, sizeof(file), "%s.%s", argv[1], argv[2]);
fd = create(file, ORDWR, 0664);
fd = ocreate(file, ORDWR, 0664);
if(fd < 0){
fprint(2, "mkhash: can't create %s\n", file);
exits(syserr());

View File

@ -190,7 +190,7 @@ main(int argc, char *argv[])
}
sprint(fn, "/cfg/ndb/db.%-.24s", domname);
fd = create(fn, OWRITE, 0664);
fd = ocreate(fn, OWRITE, 0664);
if(fd < 0){
fprint(2, "can't create %s: %r\n", fn);
exits("boom");
@ -201,7 +201,7 @@ main(int argc, char *argv[])
close(fd);
sprint(fn, "/cfg/ndb/equiv.%-.21s", domname);
fd = create(fn, OWRITE, 0664);
fd = ocreate(fn, OWRITE, 0664);
if(fd < 0){
fprint(2, "can't create %s: %r\n", fn);
exits("boom");
@ -211,7 +211,7 @@ main(int argc, char *argv[])
close(fd);
sprint(fn, "/cfg/ndb/txt.%-.23s", domname);
fd = create(fn, OWRITE, 0664);
fd = ocreate(fn, OWRITE, 0664);
if(fd < 0){
fprint(2, "can't create %s: %r\n", fn);
exits("boom");

View File

@ -207,7 +207,7 @@ main(int argc, char *argv[])
if(defmnt == 0){
char buf[64];
snprint(buf, sizeof buf, "#s/%s", service);
fd = create(buf, OWRITE|ORCLOSE, 0666);
fd = ocreate(buf, OWRITE|ORCLOSE, 0666);
if(fd < 0)
error("create failed");
sprint(buf, "%d", p[1]);

View File

@ -562,7 +562,7 @@ Executable(char *file)
int
Creat(char *file)
{
return create(file, OWRITE, 0666L);
return ocreate(file, OWRITE, 0666L);
}
int

View File

@ -89,7 +89,7 @@ post(char *name, char *envname, int srvfd)
int fd;
char buf[32];
fd = create(name, OWRITE|ORCLOSE|OCEXEC, 0600);
fd = ocreate(name, OWRITE|ORCLOSE|OCEXEC, 0600);
if(fd < 0)
error(name);
snprint(buf, sizeof(buf), "%d", srvfd);

View File

@ -22,7 +22,7 @@ tempdisk(void)
buf[5] = i;
if(access(buf, AEXIST) == 0)
continue;
fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
fd = ocreate(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
if(fd >= 0)
return fd;
}

View File

@ -55,7 +55,7 @@ writef(File *f)
if(genc)
free(genc);
genc = Strtoc(&genstr);
if((io=create(genc, OWRITE, 0666L)) < 0)
if((io=ocreate(genc, OWRITE, 0666L)) < 0)
error_r(Ecreate, genc);
dprint("%s: ", genc);
if(statfd(io, 0, 0, 0, &length, &appendonly) > 0 && appendonly && length>0)

View File

@ -98,7 +98,7 @@ journal(int out, char *s)
static int fd = 0;
if(fd <= 0)
fd = create("/tmp/sam.out", OWRITE, 0666L);
fd = ocreate("/tmp/sam.out", OWRITE, 0666L);
fprint(fd, "%s%s\n", out? "out: " : "in: ", s);
}

View File

@ -137,7 +137,7 @@ rescue(void)
continue;
if(io == -1){
sprint(buf, "%s/sam.save", home);
io = create(buf, OWRITE, 0777);
io = ocreate(buf, OWRITE, 0777);
if(io<0)
return;
}

View File

@ -41,9 +41,9 @@ plan9(File *f, int type, String *s, int nest)
snarf(f, addr.r.p1, addr.r.p2, &plan9buf, 1);
if((pid=fork()) == 0){
if(downloaded){ /* also put nasty fd's into errfile */
fd = create(errfile, OWRITE, 0666L);
fd = ocreate(errfile, OWRITE, 0666L);
if(fd < 0)
fd = create("/dev/null", OWRITE, 0666L);
fd = ocreate("/dev/null", OWRITE, 0666L);
dup(fd, 2);
close(fd);
/* 2 now points at err file */

View File

@ -107,7 +107,7 @@ snarfswap(char *fromsam, int nc, char **tosam)
free(s1);
} else
s1[n] = 0;
f = create("/dev/snarf", OWRITE, 0666);
f = ocreate("/dev/snarf", OWRITE, 0666);
if(f >= 0){
write(f, fromsam, nc);
close(f);
@ -167,7 +167,7 @@ extstart(void)
if(pipe(p) < 0)
return;
sprint(exname, "/srv/sam.%s", getuser());
fd = create(exname, OWRITE, 0600);
fd = ocreate(exname, OWRITE, 0600);
if(fd < 0){ /* assume existing guy is more important */
Err:
close(p[0]);

View File

@ -616,7 +616,7 @@ open_file(char *name)
if ((bp = malloc(sizeof(Biobuf))) == 0)
quit("Out of memory");
if ((fd = open(name, OWRITE)) < 0 &&
(fd = create(name, OWRITE, 0666)) < 0)
(fd = ocreate(name, OWRITE, 0666)) < 0)
quit("Cannot create %s", name);
Binit(bp, fd, OWRITE);
Bseek(bp, 0, 2);

View File

@ -191,7 +191,7 @@ main(int argc, char *argv[])
f = 1;
if(args.ofile) {
f = create(args.ofile, OWRITE, 0666);
f = ocreate(args.ofile, OWRITE, 0666);
if(f < 0) {
fprint(2, "sort: create %s: %r\n", args.ofile);
done("create");
@ -334,7 +334,7 @@ tempout(void)
sort4(args.linep, args.nline);
tf = tempfile(args.ntemp);
args.ntemp++;
f = create(tf, OWRITE, 0666);
f = ocreate(tf, OWRITE, 0666);
if(f < 0) {
fprint(2, "sort: create %s: %r\n", tf);
done("create");
@ -410,7 +410,7 @@ mergeout(Biobuf *b)
if(n > Nmerge) {
tf = tempfile(args.ntemp);
args.ntemp++;
f = create(tf, OWRITE, 0666);
f = ocreate(tf, OWRITE, 0666);
if(f < 0) {
fprint(2, "sort: create %s: %r\n", tf);
done("create");

View File

@ -162,7 +162,7 @@ openf(void)
Bterm(output);
if(fd > 0)
close(fd);
fd = create(name,OWRITE,0666);
fd = ocreate(name,OWRITE,0666);
if(fd < 0) {
fprint(2, "grep: can't create %s: %r\n", name);
exits("create");

View File

@ -228,7 +228,7 @@ post(char *srv, int fd)
char buf[128];
fprint(2, "post...\n");
f = create(srv, OWRITE, 0666);
f = ocreate(srv, OWRITE, 0666);
if(f < 0){
sprint(buf, "create(%s)", srv);
error(buf);

View File

@ -91,7 +91,7 @@ main(int argc, char **argv)
strecpy(buf, buf+sizeof buf, argv[0]);
else
snprint(buf, sizeof buf, "/srv/%s", argv[0]);
fd = create(buf, OWRITE, perm);
fd = ocreate(buf, OWRITE, perm);
if(fd < 0){
fprint(2, "can't create %s: %r\n", buf);
exits("create");

View File

@ -882,7 +882,7 @@ replace(char **argv)
Pushstate ps;
if (usefile && docreate)
ar = create(usefile, OWRITE, 0666);
ar = ocreate(usefile, OWRITE, 0666);
else if (usefile)
ar = open(usefile, ORDWR);
else
@ -1065,10 +1065,10 @@ openfname(Hdr *hp, char *fname, int dir, int mode)
if (!keepexisting || access(fname, AEXIST) < 0) {
int rw = (dir? OREAD: OWRITE);
fd = create(fname, rw, mode);
fd = ocreate(fname, rw, mode);
if (fd < 0) {
mkpdirs(fname);
fd = create(fname, rw, mode);
fd = ocreate(fname, rw, mode);
}
if (fd < 0 && (!dir || xaccess(fname, AEXIST) < 0))
cantcreate(fname, mode);

View File

@ -56,10 +56,10 @@ main(int argc, char **argv)
if(aflag) {
openf[n] = open(argv[0], OWRITE);
if(openf[n] < 0)
openf[n] = create(argv[0], OWRITE, 0666);
openf[n] = ocreate(argv[0], OWRITE, 0666);
seek(openf[n], 0L, 2);
} else
openf[n] = create(argv[0], OWRITE, 0666);
openf[n] = ocreate(argv[0], OWRITE, 0666);
if(openf[n] < 0) {
fprint(2, "tee: cannot open %s: %r\n", argv[0]);
} else

View File

@ -65,7 +65,7 @@ touch(int nocreate, char *name)
fprint(2, "touch: %s: cannot wstat: %r\n", name);
return 1;
}
if((fd = create(name, OREAD|OEXCL, 0666)) < 0){
if((fd = create(name, OREAD, 0666)) < 0){
fprint(2, "touch: %s: cannot create: %r\n", name);
return 1;
}

View File

@ -447,7 +447,7 @@ main(int argc, char **argv)
break;
} ARGEND;
busyfd = create("/env/usbbusy", ORCLOSE, 0600);
busyfd = ocreate("/env/usbbusy", ORCLOSE, 0600);
quotefmtinstall();
initevent();
rfork(RFNOTEG);

View File

@ -609,7 +609,8 @@ faultamd64(Ureg* ureg, void* _1)
insyscall = up->insyscall;
up->insyscall = 1;
if(iskaddr(addr)){
print("kaddr %#llux pc %#p\n", addr, ureg->ip); prflush();
print("kaddr %#llux pc %#p\n", addr, ureg->ip);
// prflush();
dumpregs(ureg);
}
if(fault(addr, ureg->ip, ftype) < 0){

View File

@ -30,7 +30,7 @@ savelogsproc(void)
out = open("/sys/log/kernel", OWRITE);
if(out < 0){
out = create("/sys/log/kernel", OWRITE, 0600);
out = ocreate("/sys/log/kernel", OWRITE, 0600);
if(out < 0){
fprint(2, "savelogs: cannot create /sys/log/kernel: %r\n");
return;
@ -139,7 +139,7 @@ setenv(char *name, char *val)
char ename[64];
snprint(ename, sizeof ename, "#e/%s", name);
f = create(ename, OWRITE, 0666);
f = ocreate(ename, OWRITE, 0666);
if(f < 0){
fprint(2, "create %s: %r\n", ename);
return;
@ -162,7 +162,7 @@ srvcreate(char *name, int fd)
srvname = name;
snprint(buf, sizeof buf, "#s/%s", srvname);
f = create(buf, OWRITE, 0600);
f = ocreate(buf, OWRITE, 0600);
if(f < 0)
fatal(buf);
sprint(buf, "%d", fd);

View File

@ -1222,7 +1222,7 @@ namec(char *aname, int amode, int omode, int perm)
Elemlist e;
Rune r;
Mhead *mh;
char *createerr, tmperrbuf[ERRMAX];
char tmperrbuf[ERRMAX];
char *name;
Dev *dev;
@ -1309,13 +1309,7 @@ namec(char *aname, int amode, int omode, int perm)
dev = devtabget(r, 1); //XDYNX
if(dev == nil)
error(Ebadsharp);
//if(waserror()){
// devtabdecr(dev);
// nexterror();
//}
c = dev->attach(nil, nil, up->genbuf+n, 0);
//poperror();
//devtabdecr(dev);
break;
default:
@ -1403,7 +1397,6 @@ namec(char *aname, int amode, int omode, int perm)
case Aaccess:
case Aremove:
case Aopen:
Open:
/* save&update the name; domount might change c */
path = c->path;
incref(&path->r);
@ -1482,58 +1475,13 @@ namec(char *aname, int amode, int omode, int perm)
case Acreate:
/*
* We've already walked all but the last element.
* If the last exists, try to open it OTRUNC.
* If omode&OEXCL is set, just give up.
* If the last exists just give up.
*/
e.nelems++;
e.nerror++;
if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0){
if(omode&OEXCL)
if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0)
error(Eexist);
omode |= OTRUNC;
goto Open;
}
/*
* The semantics of the create(2) system call are that if the
* file exists and can be written, it is to be opened with truncation.
* On the other hand, the create(5) message fails if the file exists.
* If we get two create(2) calls happening simultaneously,
* they might both get here and send create(5) messages, but only
* one of the messages will succeed. To provide the expected create(2)
* semantics, the call with the failed message needs to try the above
* walk again, opening for truncation. This correctly solves the
* create/create race, in the sense that any observable outcome can
* be explained as one happening before the other.
* The create/create race is quite common. For example, it happens
* when two rc subshells simultaneously update the same
* environment variable.
*
* The implementation still admits a create/create/remove race:
* (A) walk to file, fails
* (B) walk to file, fails
* (A) create file, succeeds, returns
* (B) create file, fails
* (A) remove file, succeeds, returns
* (B) walk to file, return failure.
*
* This is hardly as common as the create/create race, and is really
* not too much worse than what might happen if (B) got a hold of a
* file descriptor and then the file was removed -- either way (B) can't do
* anything with the result of the create call. So we don't care about this race.
*
* Applications that care about more fine-grained decision of the races
* can use the OEXCL flag to get at the underlying create(5) semantics;
* by default we provide the common case.
*
* We need to stay behind the mount point in case we
* need to do the first walk again (should the create fail).
*
* We also need to cross the mount point and find the directory
* in the union in which we should be creating.
*
* The channel staying behind is c, the one moving forward is cnew.
*/
mh = nil;
cnew = nil; /* is this assignment necessary? */
if(!waserror()){ /* try create */
@ -1555,7 +1503,7 @@ namec(char *aname, int amode, int omode, int perm)
cnew->path = c->path;
incref(&cnew->path->r);
cnew = cnew->dev->create(cnew, e.elems[e.nelems-1], omode&~(OEXCL|OCEXEC), perm);
cnew = cnew->dev->create(cnew, e.elems[e.nelems-1], omode&~(OCEXEC), perm);
poperror();
if(omode & OCEXEC)
cnew->flag |= CCEXEC;
@ -1570,19 +1518,7 @@ namec(char *aname, int amode, int omode, int perm)
/* create failed */
cclose(cnew);
putmhead(mh);
if(omode & OEXCL)
nexterror();
/* save error */
createerr = up->errstr;
up->errstr = tmperrbuf;
/* note: we depend that walk does not error */
if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0){
up->errstr = createerr;
error(createerr); /* report true error */
}
up->errstr = createerr;
omode |= OTRUNC;
goto Open;
default:
panic("unknown namec access %d", amode);

View File

@ -498,7 +498,7 @@ ninep2mode(int omode9p)
if((omode9p&~0xff) || (omode9p&NP_OZEROES))
error("invalid 9P2000 open mode");
switch(omode9p & ~(NP_OTRUNC|NP_ORCLOSE)){
switch(omode9p & ~(NP_OTRUNC|NP_ORCLOSE|NP_OCEXEC)){
case NP_OREAD:
return OREAD;
case NP_OWRITE:
@ -513,10 +513,12 @@ ninep2mode(int omode9p)
default:
error("invalid 9P2000 open mode");
}
if(omode9p & NP_OTRUNC)
mode |= OTRUNC;
if(omode9p & NP_OCEXEC)
mode |= OCEXEC;
if(omode9p & NP_ORCLOSE)
mode |= ORCLOSE;
if(omode9p & NP_OTRUNC)
mode |= OTRUNC;
return mode;
}
@ -542,6 +544,8 @@ mode2ninep(unsigned long mode)
omode9p |= NP_OEXEC;
if(mode & ORCLOSE)
omode9p |= NP_ORCLOSE;
if(mode & OCEXEC)
omode9p |= NP_OCEXEC;
/* this is an approssimation: in Jehanne this bit might means
* something different to a server, but then the

View File

@ -245,11 +245,9 @@ void
prflush(void)
{
unsigned long now;
// uint32_t now;
now = sys->ticks;
while(consactive())
// uartpush();
if(sys->ticks - now >= 30*HZ)
break;
}
@ -365,7 +363,6 @@ print(char *fmt, ...)
n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
va_end(arg);
putstrn(buf, n);
if(strchr(buf, '\n') != nil)prflush();
return n;
}
@ -452,7 +449,7 @@ panic(char *fmt, ...)
buf[n] = '\n';
putstrn(buf, n+1);
// dumpstack();
prflush();
// prflush();
// dump();
exit(1);

View File

@ -157,7 +157,7 @@ srvcreate(Chan *c, char *name, unsigned long omode, unsigned long perm)
{
Srv *sp;
if(openmode(omode & ~ORCLOSE) != OWRITE){
if(openmode(omode & ~(ORCLOSE|OTRUNC)) != OWRITE){
errorf("srvcreate: omode %#p openmode %#p", omode, openmode(omode & ~ORCLOSE));
//error(Eperm);
}

View File

@ -204,7 +204,6 @@ extern uint64_t strtoull(char*, char**, int);
/* OPEN MODES: Popular flags among filesystems */
#define OTRUNC 0x0100 /* or'ed in (except for exec), truncate file first */
#define OEXCL 0x0200 /* or'ed in, exclusive create */
#define NCONT 0 /* continue after note */
#define NDFLT 1 /* terminate after note */

View File

@ -1030,7 +1030,7 @@ syscreate(char* aname, uint32_t omode, uint32_t perm)
int fd;
Chan *c;
openmode(omode & ~OEXCL); /* error check only; OEXCL okay here */
openmode(omode); /* error check only; OEXCL okay here */
c = nil;
if(waserror()) {
if(c != nil)

View File

@ -410,7 +410,7 @@ sopen(Srv *srv, Req *r)
respond(r, Ebotch);
return;
}
if((r->fid->qid.type&QTDIR) && (r->ifcall.mode&~ORCLOSE) != NP_OREAD){
if((r->fid->qid.type&QTDIR) && (r->ifcall.mode&~NP_ORCLOSE) != NP_OREAD){
respond(r, Eisdir);
return;
}
@ -537,7 +537,7 @@ sread(Srv *srv, Req *r)
r->ifcall.count = srv->msize - IOHDRSZ;
r->rbuf = emalloc9p(r->ifcall.count);
r->ofcall.data = r->rbuf;
o = r->fid->omode & 7;
o = r->fid->omode & 3;
if(o != NP_OREAD && o != NP_ORDWR && o != NP_OEXEC){
respond(r, Ebotch);
return;
@ -579,7 +579,7 @@ swrite(Srv *srv, Req *r)
}
if(r->ifcall.count > srv->msize - IOHDRSZ)
r->ifcall.count = srv->msize - IOHDRSZ;
o = r->fid->omode & 7;
o = r->fid->omode & 3;
if(o != NP_OWRITE && o != NP_ORDWR){
snprint(e, sizeof e, "write on fid with open mode 0x%ux", r->fid->omode);
respond(r, e);
@ -952,7 +952,7 @@ postfd(char *name, int pfd)
snprint(buf, sizeof buf, "/srv/%s", name);
if(chatty9p)
fprint(2, "postfd %s\n", buf);
fd = create(buf, OWRITE|ORCLOSE|OCEXEC, 0600);
fd = ocreate(buf, OWRITE|ORCLOSE|OCEXEC, 0600);
if(fd < 0){
if(chatty9p)
fprint(2, "create fails: %r\n");
@ -981,7 +981,7 @@ sharefd(char *name, char *desc, int pfd)
snprint(buf, sizeof buf, "#σc/%s/%s", name, desc);
if(chatty9p)
fprint(2, "sharefd %s\n", buf);
fd = create(buf, OWRITE, 0600);
fd = ocreate(buf, OWRITE, 0600);
if(fd < 0){
if(chatty9p)
fprint(2, "create fails: %r\n");

View File

@ -340,7 +340,7 @@ setenv(char *name, char *val)
int32_t s;
sprint(ename, "#e/%s", name);
f = create(ename, OWRITE, 0664);
f = ocreate(ename, OWRITE, 0664);
if(f < 0)
return -1;
s = strlen(val);

View File

@ -133,7 +133,7 @@ Bopen(char *name, int mode)
f = open(name, mode);
break;
case OWRITE:
f = create(name, mode, 0666);
f = ocreate(name, mode, 0666);
break;
}
if(f < 0)

View File

@ -15,7 +15,17 @@ access(const char *name, int mode)
{
int fd;
Dir *db;
mode &= AMASK;
static char omode[] = {
0,
OEXEC,
OWRITE,
ORDWR,
OREAD,
OEXEC, /* only approximate */
ORDWR,
ORDWR /* only approximate */
};
if(mode == AEXIST){
db = dirstat(name);
@ -24,7 +34,7 @@ access(const char *name, int mode)
return 0;
return -1;
}
fd = open(name, mode);
fd = open(name, omode[mode&7]);
if(fd >= 0){
close(fd);
return 0;

View File

@ -0,0 +1,69 @@
/*
* This file is part of Jehanne.
*
* Copyright (C) 2016 Giacomo Tesio <giacomo@tesio.it>
*
* Jehanne is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2 of the License.
*
* Jehanne is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
*/
#include <u.h>
#include <libc.h>
/* ocreate works like the Plan 9 create(2) syscall, but with different races.
* In Plan 9 tjere os a race due to the different behaviour between the
* create syscall and the Tcreate message in 9P2000 when the file already exists:
* see https://github.com/brho/plan9/blob/master/sys/src/9/port/chan.c#L1564-L1603
* for details.
*
* In Jehanne the create syscall fails on existing files just like the Tcreate message.
* However the Plan 9/UNIX semantic is often useful, thus ocreate mimic it in userspace.
* As wisely noted by Charles Forsyth, such implementation introduce a different race
* due to the multiple evaluations of the path: on concurrent namespace changes, the
* different syscalls here could be handled by different devices/fileservers.
* However, given the user is responsible of such namespace changes, we prefer this race
* to the original Plan 9 one.
*
* For more info see http://marc.info/?t=146412533100003&r=1&w=2
*/
int
ocreate(const char *path, unsigned int omode, unsigned int perm)
{
int fd;
Dir *s;
fd = open(path, omode|OTRUNC);
if(fd < 0){
fd = create(path, omode, perm);
if(fd < 0){
fd = open(path, omode|OTRUNC);
if(fd < 0)
goto Done;
} else {
goto Done;
}
}
s = dirfstat(fd);
if(s == nil){
close(fd);
return -1;
}
if(s->mode != perm){
s->mode = perm;
dirfwstat(fd, s); /* we ignore the return value, the device/server is allowed to ignore us */
}
free(s);
Done:
return fd;
}

View File

@ -24,12 +24,12 @@ putenv(const char *name, const char *val)
snprint(ename, sizeof ename, "/env/%s", name);
if(strcmp(ename+5, name) != 0)
return -1;
f = create(ename, OWRITE, 0664);
f = ocreate(ename, OWRITE, 0664);
if(f < 0){
/* try with #e, in case of a previous rfork(RFCNAMEG)
*/
snprint(ename, sizeof ename, "#e/%s", name);
f = create(ename, OWRITE, 0664);
f = ocreate(ename, OWRITE, 0664);
if(f < 0)
return -1;
return -1;

View File

@ -59,6 +59,7 @@
"9sys/getwd.c",
"9sys/iounit.c",
"9sys/nulldir.c",
"9sys/ocreate.c",
"9sys/pipe.c",
"9sys/postnote.c",
"9sys/privalloc.c",

View File

@ -102,7 +102,7 @@ geninitdraw(char *devdir, void(*error)(Display*, char*),
if(fd >= 0){
read(fd, display->oldlabel, (sizeof display->oldlabel)-1);
close(fd);
fd = create(buf, OWRITE, 0666);
fd = ocreate(buf, OWRITE, 0666);
if(fd >= 0){
write(fd, label, strlen(label));
close(fd);

View File

@ -51,7 +51,7 @@ plumbopen(char *name, int omode)
/* try creating port; used by non-standard plumb implementations */
rerrstr(err, sizeof err);
fd = create(buf, omode, 0600);
fd = ocreate(buf, omode, 0600);
if(fd >= 0)
return fd;
errstr(err, sizeof err);

View File

@ -42,13 +42,13 @@ FILE *freopen(const char *name, const char *mode, FILE *f){
f->fd=open(name, (*mode == '+'? ORDWR: OREAD));
break;
case 'w':
f->fd=create(name, (*mode == '+'? ORDWR: OWRITE), 0666);
f->fd=ocreate(name, (*mode == '+'? ORDWR: OWRITE), 0666);
break;
case 'a':
m = (*mode == '+'? ORDWR: OWRITE);
f->fd=open(name, m);
if(f->fd<0)
f->fd=create(name, m, 0666);
f->fd=ocreate(name, m, 0666);
seek(f->fd, 0LL, 2);
break;
}