hjfs: ORCLOSE parent check, estrdup / erealloc, CHFNOPERM consistency
check for write premission in the parent directory for open with ORCLOSE. honor CHFNOPERM not just in chancreat(), pikeshedd the error handling. added estrdup()/erealloc() that call sysfatal instead of returning nil.
This commit is contained in:
parent
28452d3fe5
commit
bcaf52ebcd
|
@ -78,14 +78,14 @@ usersparseline(char *l, PUser **u, int *nu)
|
||||||
free(v.memb);
|
free(v.memb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
v.memb = realloc(v.memb, (v.nmemb + 1) * USERLEN);
|
v.memb = erealloc(v.memb, (v.nmemb + 1) * USERLEN);
|
||||||
strcpy(v.memb[v.nmemb++], r);
|
strcpy(v.memb[v.nmemb++], r);
|
||||||
if(s == nil)
|
if(s == nil)
|
||||||
r = nil;
|
r = nil;
|
||||||
else
|
else
|
||||||
r = s + 1;
|
r = s + 1;
|
||||||
}
|
}
|
||||||
*u = realloc(*u, (*nu + 1) * sizeof(PUser));
|
*u = erealloc(*u, (*nu + 1) * sizeof(PUser));
|
||||||
memcpy(&(*u)[(*nu)++], &v, sizeof(PUser));
|
memcpy(&(*u)[(*nu)++], &v, sizeof(PUser));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ usersload(Fs *fs, Chan *ch)
|
||||||
nu = 0;
|
nu = 0;
|
||||||
for(;;){
|
for(;;){
|
||||||
if((bufl & 1023) == 0)
|
if((bufl & 1023) == 0)
|
||||||
buf = realloc(buf, bufl + 1024);
|
buf = erealloc(buf, bufl + 1024);
|
||||||
rc = chanread(ch, buf + bufl, 1024, bufl);
|
rc = chanread(ch, buf + bufl, 1024, bufl);
|
||||||
if(rc < 0)
|
if(rc < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -411,7 +411,7 @@ cmdnewuser(int argc, char **argv)
|
||||||
gid++;
|
gid++;
|
||||||
}
|
}
|
||||||
resort = 1;
|
resort = 1;
|
||||||
fs->udata = realloc(fs->udata, sizeof(User) * (fs->nudata + 1));
|
fs->udata = erealloc(fs->udata, sizeof(User) * (fs->nudata + 1));
|
||||||
u = fs->udata + fs->nudata++;
|
u = fs->udata + fs->nudata++;
|
||||||
strcpy(u->name, argv[1]);
|
strcpy(u->name, argv[1]);
|
||||||
u->nmemb = 0;
|
u->nmemb = 0;
|
||||||
|
@ -447,9 +447,9 @@ found:
|
||||||
if(u->memb[j] != v->uid)
|
if(u->memb[j] != v->uid)
|
||||||
goto erropt;
|
goto erropt;
|
||||||
memmove(&u->memb[j], &u->memb[j + 1], sizeof(short) * (u->nmemb - j - 1));
|
memmove(&u->memb[j], &u->memb[j + 1], sizeof(short) * (u->nmemb - j - 1));
|
||||||
u->memb = realloc(u->memb, sizeof(short) * --u->nmemb);
|
u->memb = erealloc(u->memb, sizeof(short) * --u->nmemb);
|
||||||
}else{
|
}else{
|
||||||
u->memb = realloc(u->memb, sizeof(short) * ++u->nmemb);
|
u->memb = erealloc(u->memb, sizeof(short) * ++u->nmemb);
|
||||||
memmove(&u->memb[j + 1], &u->memb[j], sizeof(short) * (u->nmemb - j - 1));
|
memmove(&u->memb[j + 1], &u->memb[j], sizeof(short) * (u->nmemb - j - 1));
|
||||||
u->memb[j] = v->uid;
|
u->memb[j] = v->uid;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ newdev(char *file)
|
||||||
werrstr("device file too short");
|
werrstr("device file too short");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
d->name = strdup(file);
|
d->name = estrdup(file);
|
||||||
for(b = d->buf; b < d->buf + BUFHASH + 1; b++)
|
for(b = d->buf; b < d->buf + BUFHASH + 1; b++)
|
||||||
b->dnext = b->dprev = b;
|
b->dnext = b->dprev = b;
|
||||||
d->workr.l = &d->workl;
|
d->workr.l = &d->workl;
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
void* emalloc(int);
|
void* emalloc(int);
|
||||||
|
void* erealloc(void*,int);
|
||||||
|
char* estrdup(char*);
|
||||||
void bufinit(int);
|
void bufinit(int);
|
||||||
Buf* getbuf(Dev *, uvlong, int, int);
|
Buf* getbuf(Dev *, uvlong, int, int);
|
||||||
void putbuf(Buf *);
|
void putbuf(Buf *);
|
||||||
|
|
|
@ -110,32 +110,21 @@ chancreat(Chan *ch, char *name, int perm, int mode)
|
||||||
Loc *l;
|
Loc *l;
|
||||||
FLoc f;
|
FLoc f;
|
||||||
|
|
||||||
if((ch->flags & CHFRO) != 0){
|
b = nil;
|
||||||
werrstr(Einval);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
chbegin(ch);
|
|
||||||
if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0){
|
|
||||||
chend(ch);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(!namevalid(name) || ch->open != 0){
|
|
||||||
werrstr(Einval);
|
|
||||||
chend(ch);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(isdir = ((perm & DMDIR) != 0))
|
|
||||||
if((mode & (OWRITE | OEXEC | ORCLOSE | OTRUNC)) != 0){
|
|
||||||
werrstr(Einval);
|
|
||||||
chend(ch);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
|
|
||||||
if(b == nil){
|
|
||||||
chend(ch);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
l = nil;
|
l = nil;
|
||||||
|
chbegin(ch);
|
||||||
|
if(!namevalid(name) || ch->open != 0)
|
||||||
|
goto inval;
|
||||||
|
if((ch->flags & CHFRO) != 0)
|
||||||
|
goto inval;
|
||||||
|
if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0)
|
||||||
|
goto error;
|
||||||
|
if(isdir = ((perm & DMDIR) != 0))
|
||||||
|
if((mode & (OWRITE | OEXEC | ORCLOSE | OTRUNC)) != 0)
|
||||||
|
goto inval;
|
||||||
|
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
|
||||||
|
if(b == nil)
|
||||||
|
goto error;
|
||||||
d = getdent(ch->loc, b);
|
d = getdent(ch->loc, b);
|
||||||
if(d == nil)
|
if(d == nil)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -143,7 +132,7 @@ chancreat(Chan *ch, char *name, int perm, int mode)
|
||||||
werrstr(Enotadir);
|
werrstr(Enotadir);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if((ch->flags & CHFNOPERM) == 0) /* for console */
|
if((ch->flags & CHFNOPERM) == 0)
|
||||||
if(!permcheck(ch->fs, d, ch->uid, OWRITE)){
|
if(!permcheck(ch->fs, d, ch->uid, OWRITE)){
|
||||||
werrstr(Eperm);
|
werrstr(Eperm);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -162,7 +151,6 @@ chancreat(Chan *ch, char *name, int perm, int mode)
|
||||||
b->op |= BDELWRI;
|
b->op |= BDELWRI;
|
||||||
putbuf(b);
|
putbuf(b);
|
||||||
b = nil;
|
b = nil;
|
||||||
|
|
||||||
if(willmodify(ch->fs, l, ch->flags & CHFNOLOCK) < 0)
|
if(willmodify(ch->fs, l, ch->flags & CHFNOLOCK) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
b = getbuf(ch->fs->d, l->blk, TDENTRY, 0);
|
b = getbuf(ch->fs->d, l->blk, TDENTRY, 0);
|
||||||
|
@ -185,7 +173,6 @@ chancreat(Chan *ch, char *name, int perm, int mode)
|
||||||
}
|
}
|
||||||
b->op |= BDELWRI;
|
b->op |= BDELWRI;
|
||||||
putbuf(b);
|
putbuf(b);
|
||||||
|
|
||||||
switch(mode & OEXEC){
|
switch(mode & OEXEC){
|
||||||
case ORDWR:
|
case ORDWR:
|
||||||
ch->open |= CHREAD;
|
ch->open |= CHREAD;
|
||||||
|
@ -199,7 +186,8 @@ chancreat(Chan *ch, char *name, int perm, int mode)
|
||||||
}
|
}
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return 1;
|
return 1;
|
||||||
|
inval:
|
||||||
|
werrstr(Einval);
|
||||||
error:
|
error:
|
||||||
if(l != nil)
|
if(l != nil)
|
||||||
putloc(ch->fs, l, 0);
|
putloc(ch->fs, l, 0);
|
||||||
|
@ -214,47 +202,45 @@ chanopen(Chan *ch, int mode)
|
||||||
{
|
{
|
||||||
Buf *b;
|
Buf *b;
|
||||||
Dentry *d;
|
Dentry *d;
|
||||||
int isdir;
|
|
||||||
|
|
||||||
|
b = nil;
|
||||||
chbegin(ch);
|
chbegin(ch);
|
||||||
if(ch->open != 0){
|
if(ch->open != 0)
|
||||||
werrstr(Einval);
|
goto inval;
|
||||||
chend(ch);
|
if((ch->flags & CHFRO) != 0 && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0)
|
||||||
return -1;
|
goto inval;
|
||||||
}
|
|
||||||
if((mode & OTRUNC) != 0)
|
if((mode & OTRUNC) != 0)
|
||||||
if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0){
|
if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0)
|
||||||
chend(ch);
|
goto error;
|
||||||
return -1;
|
if((mode & ORCLOSE) != 0){
|
||||||
}
|
if(ch->loc->next == nil)
|
||||||
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
|
goto inval;
|
||||||
if(b == nil){
|
b = getbuf(ch->fs->d, ch->loc->next->blk, TDENTRY, 0);
|
||||||
chend(ch);
|
if(b == nil)
|
||||||
return -1;
|
goto error;
|
||||||
|
d = getdent(ch->loc->next, b);
|
||||||
|
if(d == nil)
|
||||||
|
goto error;
|
||||||
|
if((ch->flags & CHFNOPERM) == 0)
|
||||||
|
if(!permcheck(ch->fs, d, ch->uid, OWRITE))
|
||||||
|
goto perm;
|
||||||
|
putbuf(b);
|
||||||
}
|
}
|
||||||
|
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
|
||||||
|
if(b == nil)
|
||||||
|
goto error;
|
||||||
d = getdent(ch->loc, b);
|
d = getdent(ch->loc, b);
|
||||||
if(d == nil)
|
if(d == nil)
|
||||||
goto err;
|
goto error;
|
||||||
if(!permcheck(ch->fs, d, ch->uid, mode & OEXEC)){
|
|
||||||
permerr:
|
|
||||||
werrstr(Eperm);
|
|
||||||
err:
|
|
||||||
putbuf(b);
|
|
||||||
chend(ch);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if((d->type & QTAPPEND) != 0)
|
if((d->type & QTAPPEND) != 0)
|
||||||
mode &= ~OTRUNC;
|
mode &= ~OTRUNC;
|
||||||
isdir = (d->type & QTDIR) != 0;
|
if((d->type & QTDIR) != 0 && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0)
|
||||||
if(isdir && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0){
|
goto inval;
|
||||||
werrstr(Einval);
|
if((ch->flags & CHFNOPERM) == 0){
|
||||||
goto err;
|
if(!permcheck(ch->fs, d, ch->uid, mode & OEXEC))
|
||||||
}
|
goto perm;
|
||||||
if((mode & OTRUNC) != 0 && !permcheck(ch->fs, d, ch->uid, OWRITE))
|
if((mode & OTRUNC) != 0 && !permcheck(ch->fs, d, ch->uid, OWRITE))
|
||||||
goto permerr;
|
goto perm;
|
||||||
if((ch->flags & CHFRO) != 0 && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0){
|
|
||||||
werrstr(Einval);
|
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
if((ch->loc->type & QTEXCL) != 0){
|
if((ch->loc->type & QTEXCL) != 0){
|
||||||
qlock(&ch->loc->ex);
|
qlock(&ch->loc->ex);
|
||||||
|
@ -265,7 +251,7 @@ chanopen(Chan *ch, int mode)
|
||||||
}else{
|
}else{
|
||||||
qunlock(&ch->loc->ex);
|
qunlock(&ch->loc->ex);
|
||||||
werrstr(Elocked);
|
werrstr(Elocked);
|
||||||
goto err;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch(mode & OEXEC){
|
switch(mode & OEXEC){
|
||||||
|
@ -289,6 +275,16 @@ chanopen(Chan *ch, int mode)
|
||||||
putbuf(b);
|
putbuf(b);
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return 1;
|
return 1;
|
||||||
|
inval:
|
||||||
|
werrstr(Einval);
|
||||||
|
goto error;
|
||||||
|
perm:
|
||||||
|
werrstr(Eperm);
|
||||||
|
error:
|
||||||
|
if(b != nil)
|
||||||
|
putbuf(b);
|
||||||
|
chend(ch);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -401,13 +397,12 @@ chanread(Chan *ch, void *buf, ulong n, uvlong off)
|
||||||
Buf *b, *c;
|
Buf *b, *c;
|
||||||
Dentry *d;
|
Dentry *d;
|
||||||
|
|
||||||
chbegin(ch);
|
|
||||||
if((ch->loc->type & QTEXCL) != 0 && checklock(ch) < 0){
|
|
||||||
chend(ch);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if((ch->open & CHREAD) == 0){
|
if((ch->open & CHREAD) == 0){
|
||||||
werrstr(Einval);
|
werrstr(Einval);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
chbegin(ch);
|
||||||
|
if((ch->loc->type & QTEXCL) != 0 && checklock(ch) < 0){
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -419,11 +414,8 @@ chanread(Chan *ch, void *buf, ulong n, uvlong off)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
d = getdent(ch->loc, b);
|
d = getdent(ch->loc, b);
|
||||||
if(d == nil){
|
if(d == nil)
|
||||||
putbuf(b);
|
goto error;
|
||||||
chend(ch);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(off >= d->size)
|
if(off >= d->size)
|
||||||
n = 0;
|
n = 0;
|
||||||
else if(off + n > d->size)
|
else if(off + n > d->size)
|
||||||
|
@ -460,7 +452,6 @@ chanread(Chan *ch, void *buf, ulong n, uvlong off)
|
||||||
putbuf(b);
|
putbuf(b);
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return n;
|
return n;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
putbuf(b);
|
putbuf(b);
|
||||||
chend(ch);
|
chend(ch);
|
||||||
|
@ -478,7 +469,7 @@ statbuf(Fs *fs, Dentry *d, Dir *di, char *buf)
|
||||||
if(d->type & QTDIR)
|
if(d->type & QTDIR)
|
||||||
di->length = 0;
|
di->length = 0;
|
||||||
if(buf == nil){
|
if(buf == nil){
|
||||||
di->name = strdup(d->name);
|
di->name = estrdup(d->name);
|
||||||
di->uid = uid2name(fs, d->uid, nil);
|
di->uid = uid2name(fs, d->uid, nil);
|
||||||
di->gid = uid2name(fs, d->gid, nil);
|
di->gid = uid2name(fs, d->gid, nil);
|
||||||
di->muid = uid2name(fs, d->muid, nil);
|
di->muid = uid2name(fs, d->muid, nil);
|
||||||
|
@ -612,37 +603,33 @@ chanclunk(Chan *ch)
|
||||||
int rc;
|
int rc;
|
||||||
Dentry *d;
|
Dentry *d;
|
||||||
|
|
||||||
chbegin(ch);
|
|
||||||
rc = 1;
|
rc = 1;
|
||||||
b = p = nil;
|
b = p = nil;
|
||||||
|
chbegin(ch);
|
||||||
if(ch->open & CHRCLOSE){
|
if(ch->open & CHRCLOSE){
|
||||||
if((ch->flags & CHFRO) != 0)
|
if((ch->flags & CHFRO) != 0)
|
||||||
goto inval;
|
goto inval;
|
||||||
if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0)
|
if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0)
|
||||||
goto err;
|
goto error;
|
||||||
if(ch->loc->next == nil){
|
if(ch->loc->next == nil)
|
||||||
inval:
|
goto inval;
|
||||||
werrstr(Einval);
|
|
||||||
err:
|
|
||||||
rc = -1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
p = getbuf(ch->fs->d, ch->loc->next->blk, TDENTRY, 0);
|
p = getbuf(ch->fs->d, ch->loc->next->blk, TDENTRY, 0);
|
||||||
if(p == nil)
|
if(p == nil)
|
||||||
goto err;
|
goto error;
|
||||||
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
|
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
|
||||||
if(b == nil)
|
if(b == nil)
|
||||||
goto err;
|
goto error;
|
||||||
d = getdent(ch->loc->next, p);
|
d = getdent(ch->loc->next, p);
|
||||||
if(d == nil)
|
if(d == nil)
|
||||||
goto err;
|
goto error;
|
||||||
if(!permcheck(ch->fs, d, ch->uid, OWRITE)){
|
if((ch->flags & CHFNOPERM) == 0)
|
||||||
werrstr(Eperm);
|
if(!permcheck(ch->fs, d, ch->uid, OWRITE)){
|
||||||
goto err;
|
werrstr(Eperm);
|
||||||
}
|
goto error;
|
||||||
|
}
|
||||||
d = getdent(ch->loc, b);
|
d = getdent(ch->loc, b);
|
||||||
if(d == nil)
|
if(d == nil)
|
||||||
goto err;
|
goto error;
|
||||||
if((d->type & QTDIR) != 0 && findentry(ch->fs, ch->loc, b, nil, nil, ch->flags & CHFDUMP) != 0)
|
if((d->type & QTDIR) != 0 && findentry(ch->fs, ch->loc, b, nil, nil, ch->flags & CHFDUMP) != 0)
|
||||||
goto inval;
|
goto inval;
|
||||||
if((d->mode & DGONE) != 0)
|
if((d->mode & DGONE) != 0)
|
||||||
|
@ -675,6 +662,11 @@ done:
|
||||||
chend(ch);
|
chend(ch);
|
||||||
free(ch);
|
free(ch);
|
||||||
return rc;
|
return rc;
|
||||||
|
inval:
|
||||||
|
werrstr(Einval);
|
||||||
|
error:
|
||||||
|
rc = -1;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -685,16 +677,12 @@ chanwstat(Chan *ch, Dir *di)
|
||||||
int isdir, owner, rc;
|
int isdir, owner, rc;
|
||||||
short nuid, ngid;
|
short nuid, ngid;
|
||||||
|
|
||||||
if((ch->flags & CHFRO) != 0){
|
|
||||||
werrstr(Einval);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
chbegin(ch);
|
|
||||||
if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0){
|
|
||||||
chend(ch);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
b = pb = nil;
|
b = pb = nil;
|
||||||
|
chbegin(ch);
|
||||||
|
if((ch->flags & CHFRO) != 0)
|
||||||
|
goto inval;
|
||||||
|
if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0)
|
||||||
|
goto error;
|
||||||
if(*di->name){
|
if(*di->name){
|
||||||
if(!namevalid(di->name) || ch->loc->next == nil)
|
if(!namevalid(di->name) || ch->loc->next == nil)
|
||||||
goto inval;
|
goto inval;
|
||||||
|
@ -704,8 +692,9 @@ chanwstat(Chan *ch, Dir *di)
|
||||||
d = getdent(ch->loc->next, pb);
|
d = getdent(ch->loc->next, pb);
|
||||||
if(d == nil)
|
if(d == nil)
|
||||||
goto error;
|
goto error;
|
||||||
if(!permcheck(ch->fs, d, ch->uid, OWRITE))
|
if((ch->flags & CHFNOPERM) == 0)
|
||||||
goto perm;
|
if(!permcheck(ch->fs, d, ch->uid, OWRITE))
|
||||||
|
goto perm;
|
||||||
rc = findentry(ch->fs, ch->loc->next, pb, di->name, nil, ch->flags & CHFDUMP);
|
rc = findentry(ch->fs, ch->loc->next, pb, di->name, nil, ch->flags & CHFDUMP);
|
||||||
if(rc > 0)
|
if(rc > 0)
|
||||||
werrstr(Eexists);
|
werrstr(Eexists);
|
||||||
|
@ -719,12 +708,16 @@ chanwstat(Chan *ch, Dir *di)
|
||||||
if(d == nil)
|
if(d == nil)
|
||||||
goto error;
|
goto error;
|
||||||
isdir = (d->type & QTDIR) != 0;
|
isdir = (d->type & QTDIR) != 0;
|
||||||
owner = ch->uid == d->uid || ingroup(ch->fs, ch->uid, d->gid, 1) || (ch->fs->flags & FSNOPERM) != 0;
|
owner = ch->uid == d->uid ||
|
||||||
|
ingroup(ch->fs, ch->uid, d->gid, 1) ||
|
||||||
|
(ch->fs->flags & FSNOPERM) != 0 ||
|
||||||
|
(ch->flags & CHFNOPERM) != 0;
|
||||||
if((uvlong)~di->length){
|
if((uvlong)~di->length){
|
||||||
if(isdir && di->length != 0)
|
if(isdir && di->length != 0)
|
||||||
goto inval;
|
goto inval;
|
||||||
if(di->length != d->size && !permcheck(ch->fs, d, ch->uid, OWRITE))
|
if((ch->flags & CHFNOPERM) == 0)
|
||||||
goto perm;
|
if(di->length != d->size && !permcheck(ch->fs, d, ch->uid, OWRITE))
|
||||||
|
goto perm;
|
||||||
}
|
}
|
||||||
if((ulong)~di->atime)
|
if((ulong)~di->atime)
|
||||||
goto inval;
|
goto inval;
|
||||||
|
@ -742,7 +735,6 @@ chanwstat(Chan *ch, Dir *di)
|
||||||
goto inval;
|
goto inval;
|
||||||
if((nuid != NOUID || ngid != NOUID) && !owner)
|
if((nuid != NOUID || ngid != NOUID) && !owner)
|
||||||
goto perm;
|
goto perm;
|
||||||
|
|
||||||
if((uvlong)~di->length && !isdir){
|
if((uvlong)~di->length && !isdir){
|
||||||
trunc(ch->fs, ch->loc, b, di->length);
|
trunc(ch->fs, ch->loc, b, di->length);
|
||||||
modified(ch, d);
|
modified(ch, d);
|
||||||
|
@ -767,7 +759,6 @@ chanwstat(Chan *ch, Dir *di)
|
||||||
putbuf(b);
|
putbuf(b);
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
inval:
|
inval:
|
||||||
werrstr(Einval);
|
werrstr(Einval);
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -27,6 +27,26 @@ emalloc(int c)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
erealloc(void *v, int c)
|
||||||
|
{
|
||||||
|
v = realloc(v, c);
|
||||||
|
if(v == 0)
|
||||||
|
sysfatal("realloc: %r");
|
||||||
|
setrealloctag(v, getcallerpc(&c));
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
estrdup(char *s)
|
||||||
|
{
|
||||||
|
s = strdup(s);
|
||||||
|
if(s == 0)
|
||||||
|
sysfatal("strdup: %r");
|
||||||
|
setmalloctag(s, getcallerpc(&s));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
ThrData *
|
ThrData *
|
||||||
getthrdata(void)
|
getthrdata(void)
|
||||||
{
|
{
|
||||||
|
@ -88,8 +108,8 @@ threadmain(int argc, char **argv)
|
||||||
case 'r': doream++; break;
|
case 'r': doream++; break;
|
||||||
case 'S': flags |= FSNOPERM | FSCHOWN; break;
|
case 'S': flags |= FSNOPERM | FSCHOWN; break;
|
||||||
case 's': stdio++; break;
|
case 's': stdio++; break;
|
||||||
case 'f': file = strdup(EARGF(usage())); break;
|
case 'f': file = estrdup(EARGF(usage())); break;
|
||||||
case 'n': service = strdup(EARGF(usage())); break;
|
case 'n': service = estrdup(EARGF(usage())); break;
|
||||||
case 'm':
|
case 'm':
|
||||||
nbuf = muldiv(atoi(EARGF(usage())), 1048576, sizeof(Buf));
|
nbuf = muldiv(atoi(EARGF(usage())), 1048576, sizeof(Buf));
|
||||||
if(nbuf < 10)
|
if(nbuf < 10)
|
||||||
|
|
Loading…
Reference in a new issue