hjfs: dentry qid checking, prevent newentry() from allocating already in use slot
always check if the directory entry qid from the loc still matches the one on disk before doing anything. helps catching bugs and is basically equivalent to what cwfs does with its checktag. make a haveloc() check in newentry() to make sure we dont allocate a file slot thats still in use, but deleted. this seems to fix the NPROC>1 build problems.
This commit is contained in:
parent
ffa6f9c6ea
commit
b9bf9f1d54
|
@ -269,7 +269,8 @@ getbuf(Dev *d, uvlong off, int type, int nodata)
|
||||||
if(nodata)
|
if(nodata)
|
||||||
b->type = type;
|
b->type = type;
|
||||||
if(b->type != type && type != -1){
|
if(b->type != type && type != -1){
|
||||||
dprint("hjfs: type mismatch, dev %s, block %lld, got %T, want %T, caller %#p\n", d->name, off, b->type, type, getcallerpc(&d));
|
dprint("hjfs: type mismatch, dev %s, block %lld, got %T, want %T, caller %#p\n",
|
||||||
|
d->name, off, b->type, type, getcallerpc(&d));
|
||||||
werrstr("phase error -- type mismatch");
|
werrstr("phase error -- type mismatch");
|
||||||
putbuf(b);
|
putbuf(b);
|
||||||
return nil;
|
return nil;
|
||||||
|
|
|
@ -143,8 +143,8 @@ again:
|
||||||
p = getbuf(fs->d, l->next->blk, TDENTRY, 0);
|
p = getbuf(fs->d, l->next->blk, TDENTRY, 0);
|
||||||
if(p == nil)
|
if(p == nil)
|
||||||
goto err;
|
goto err;
|
||||||
d = &p->de[l->next->deind];
|
d = getdent(l->next, p);
|
||||||
for(i = 0; i < d->size; i++){
|
if(d != nil) for(i = 0; i < d->size; i++){
|
||||||
rc = getblk(fs, l->next, p, i, &r, GBREAD);
|
rc = getblk(fs, l->next, p, i, &r, GBREAD);
|
||||||
if(rc <= 0)
|
if(rc <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -8,6 +8,7 @@ void unpack(Buf *, uchar *);
|
||||||
Dev* newdev(char *);
|
Dev* newdev(char *);
|
||||||
ThrData* getthrdata(void);
|
ThrData* getthrdata(void);
|
||||||
Fs* initfs(Dev *, int, int);
|
Fs* initfs(Dev *, int, int);
|
||||||
|
Dentry* getdent(FLoc *, Buf *);
|
||||||
int getfree(Fs *, uvlong *);
|
int getfree(Fs *, uvlong *);
|
||||||
int putfree(Fs *, uvlong);
|
int putfree(Fs *, uvlong);
|
||||||
Chan* chanattach(Fs *, int);
|
Chan* chanattach(Fs *, int);
|
||||||
|
|
|
@ -29,6 +29,35 @@ chref(Fs *fs, uvlong r, int stat)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qidcmp(Qid *a, Qid *b)
|
||||||
|
{
|
||||||
|
if(a->type != b->type)
|
||||||
|
return 1;
|
||||||
|
if(a->path != b->path)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dentry*
|
||||||
|
getdent(FLoc *l, Buf *b)
|
||||||
|
{
|
||||||
|
Dentry *d;
|
||||||
|
|
||||||
|
d = &b->de[l->deind];
|
||||||
|
if((d->mode & (DGONE | DALLOC)) == 0){
|
||||||
|
dprint("hjfs: getdent: file gone, callerpc %#p\n", getcallerpc(&l));
|
||||||
|
werrstr("phase error -- getdent");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
if(qidcmp(d, l) != 0){
|
||||||
|
dprint("hjfs: getdent: wrong qid, callerpc %#p\n", getcallerpc(&l));
|
||||||
|
werrstr("phase error -- getdent");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
getfree(Fs *fs, uvlong *r)
|
getfree(Fs *fs, uvlong *r)
|
||||||
{
|
{
|
||||||
|
@ -364,13 +393,13 @@ haveloc(Fs *fs, uvlong blk, int deind, Loc *next)
|
||||||
|
|
||||||
qlock(&fs->loctree);
|
qlock(&fs->loctree);
|
||||||
l = next->child;
|
l = next->child;
|
||||||
do{
|
if(l != nil) do{
|
||||||
if(l->blk == blk && l->deind == deind){
|
if(l->blk == blk && l->deind == deind){
|
||||||
qunlock(&fs->loctree);
|
qunlock(&fs->loctree);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
l = l->cnext;
|
l = l->cnext;
|
||||||
}while(l != next->child);
|
} while(l != next->child);
|
||||||
qunlock(&fs->loctree);
|
qunlock(&fs->loctree);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -511,7 +540,11 @@ getblk(Fs *fs, FLoc *L, Buf *bd, uvlong blk, uvlong *r, int mode)
|
||||||
Dentry *d;
|
Dentry *d;
|
||||||
|
|
||||||
b = bd;
|
b = bd;
|
||||||
d = &bd->de[L->deind];
|
d = getdent(L, b);
|
||||||
|
if(d == nil){
|
||||||
|
dprint("hjfs: getblk: dirent gone\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if(blk < NDIRECT){
|
if(blk < NDIRECT){
|
||||||
loc = &d->db[blk];
|
loc = &d->db[blk];
|
||||||
goto found;
|
goto found;
|
||||||
|
@ -696,7 +729,9 @@ trunc(Fs *fs, FLoc *ll, Buf *bd, uvlong size)
|
||||||
uvlong l;
|
uvlong l;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
d = &bd->de[ll->deind];
|
d = getdent(ll, bd);
|
||||||
|
if(d == nil)
|
||||||
|
return -1;
|
||||||
if(size >= d->size)
|
if(size >= d->size)
|
||||||
goto done;
|
goto done;
|
||||||
blk = HOWMANY(size, RBLOCK);
|
blk = HOWMANY(size, RBLOCK);
|
||||||
|
@ -758,7 +793,9 @@ findentry(Fs *fs, FLoc *l, Buf *b, char *name, FLoc *rl, int dump)
|
||||||
uvlong r;
|
uvlong r;
|
||||||
Buf *c;
|
Buf *c;
|
||||||
|
|
||||||
d = &b->de[l->deind];
|
d = getdent(l, b);
|
||||||
|
if(d == nil)
|
||||||
|
return -1;
|
||||||
for(i = 0; i < d->size; i++){
|
for(i = 0; i < d->size; i++){
|
||||||
if(getblk(fs, l, b, i, &r, GBREAD) <= 0)
|
if(getblk(fs, l, b, i, &r, GBREAD) <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -816,7 +853,10 @@ deltraverse(Fs *fs, Del *p, Buf *b, Del **last)
|
||||||
if(b == nil)
|
if(b == nil)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
s = b->de[p->deind].size;
|
d = getdent(p, b);
|
||||||
|
if(d == nil)
|
||||||
|
return -1;
|
||||||
|
s = d->size;
|
||||||
for(i = 0; i < s; i++){
|
for(i = 0; i < s; i++){
|
||||||
rc = getblk(fs, p, b, i, &r, GBREAD);
|
rc = getblk(fs, p, b, i, &r, GBREAD);
|
||||||
if(rc <= 0)
|
if(rc <= 0)
|
||||||
|
@ -835,6 +875,7 @@ deltraverse(Fs *fs, Del *p, Buf *b, Del **last)
|
||||||
dd = emalloc(sizeof(Del));
|
dd = emalloc(sizeof(Del));
|
||||||
dd->blk = i;
|
dd->blk = i;
|
||||||
dd->deind = j;
|
dd->deind = j;
|
||||||
|
dd->Qid = d->Qid;
|
||||||
dd->prev = *last;
|
dd->prev = *last;
|
||||||
(*last)->next = dd;
|
(*last)->next = dd;
|
||||||
*last = dd;
|
*last = dd;
|
||||||
|
@ -855,7 +896,9 @@ delete(Fs *fs, FLoc *l, Buf *b)
|
||||||
Buf *c;
|
Buf *c;
|
||||||
Del *first, *last, *p, *q;
|
Del *first, *last, *p, *q;
|
||||||
|
|
||||||
d = &b->de[l->deind];
|
d = getdent(l, b);
|
||||||
|
if(d == nil)
|
||||||
|
return -1;
|
||||||
if((d->type & QTDIR) == 0){
|
if((d->type & QTDIR) == 0){
|
||||||
trunc(fs, l, b, 0);
|
trunc(fs, l, b, 0);
|
||||||
memset(d, 0, sizeof(*d));
|
memset(d, 0, sizeof(*d));
|
||||||
|
@ -873,9 +916,12 @@ delete(Fs *fs, FLoc *l, Buf *b)
|
||||||
c = getbuf(fs->d, p->blk, TDENTRY, 0);
|
c = getbuf(fs->d, p->blk, TDENTRY, 0);
|
||||||
if(c == nil)
|
if(c == nil)
|
||||||
continue;
|
continue;
|
||||||
|
d = getdent(p, c);
|
||||||
|
if(d != nil){
|
||||||
trunc(fs, p, c, 0);
|
trunc(fs, p, c, 0);
|
||||||
memset(&c->de[p->deind], 0, sizeof(Dentry));
|
memset(d, 0, sizeof(*d));
|
||||||
c->op |= BDELWRI;
|
c->op |= BDELWRI;
|
||||||
|
}
|
||||||
if(p != first)
|
if(p != first)
|
||||||
putbuf(c);
|
putbuf(c);
|
||||||
}
|
}
|
||||||
|
@ -885,16 +931,16 @@ delete(Fs *fs, FLoc *l, Buf *b)
|
||||||
int
|
int
|
||||||
newentry(Fs *fs, Loc *l, Buf *b, char *name, FLoc *res)
|
newentry(Fs *fs, Loc *l, Buf *b, char *name, FLoc *res)
|
||||||
{
|
{
|
||||||
Dentry *d;
|
Dentry *d, *dd;
|
||||||
uvlong i, si, r;
|
uvlong i, si, r;
|
||||||
int j, sj, rc;
|
int j, sj, rc;
|
||||||
Buf *c;
|
Buf *c;
|
||||||
FLoc f;
|
FLoc f;
|
||||||
|
|
||||||
si = sj = -1;
|
si = sj = -1;
|
||||||
d = &b->de[l->deind];
|
d = getdent(l, b);
|
||||||
for(i = 0; i <= d->size; i++){
|
if(d != nil) for(i = 0; i <= d->size; i++){
|
||||||
if(i == d->size && si != -1)
|
if(i >= d->size && si != -1)
|
||||||
break;
|
break;
|
||||||
rc = getblk(fs, l, b, i, &r, si == -1 ? GBCREATE : GBREAD);
|
rc = getblk(fs, l, b, i, &r, si == -1 ? GBCREATE : GBREAD);
|
||||||
if(rc < 0)
|
if(rc < 0)
|
||||||
|
@ -906,32 +952,34 @@ newentry(Fs *fs, Loc *l, Buf *b, char *name, FLoc *res)
|
||||||
continue;
|
continue;
|
||||||
if(rc == 0){
|
if(rc == 0){
|
||||||
memset(c->de, 0, sizeof(c->de));
|
memset(c->de, 0, sizeof(c->de));
|
||||||
if(i == d->size){
|
if(i >= d->size){
|
||||||
d->size++;
|
d->size = i+1;
|
||||||
b->op |= BDELWRI;
|
b->op |= BDELWRI;
|
||||||
}
|
}
|
||||||
c->op |= BDELWRI;
|
c->op |= BDELWRI;
|
||||||
}
|
}
|
||||||
for(j = 0; j < DEPERBLK; j++){
|
for(j = 0; j < DEPERBLK; j++){
|
||||||
if(si == -1 && (c->de[j].mode & DALLOC) == 0){
|
dd = &c->de[j];
|
||||||
si = i;
|
if((dd->mode & DALLOC) != 0){
|
||||||
sj = j;
|
if(strcmp(dd->name, name) == 0){
|
||||||
}
|
|
||||||
if(si == -1 && (c->de[j].mode & DGONE) != 0 && !haveloc(fs, r, j, l)){
|
|
||||||
memset(&f, 0, sizeof(f));
|
|
||||||
f.blk = r;
|
|
||||||
f.deind = j;
|
|
||||||
if(delete(fs, &f, c) >= 0){
|
|
||||||
si = i;
|
|
||||||
sj = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if((c->de[j].mode & DALLOC) != 0 &&
|
|
||||||
strcmp(c->de[j].name, name) == 0){
|
|
||||||
werrstr(Eexists);
|
werrstr(Eexists);
|
||||||
putbuf(c);
|
putbuf(c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(si != -1 || haveloc(fs, r, j, l))
|
||||||
|
continue;
|
||||||
|
if((dd->mode & DGONE) != 0){
|
||||||
|
memset(&f, 0, sizeof(f));
|
||||||
|
f.blk = r;
|
||||||
|
f.deind = j;
|
||||||
|
f.Qid = dd->Qid;
|
||||||
|
if(delete(fs, &f, c) < 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
si = i;
|
||||||
|
sj = j;
|
||||||
}
|
}
|
||||||
putbuf(c);
|
putbuf(c);
|
||||||
}
|
}
|
||||||
|
@ -942,5 +990,6 @@ newentry(Fs *fs, Loc *l, Buf *b, char *name, FLoc *res)
|
||||||
if(getblk(fs, l, b, si, &res->blk, GBWRITE) <= 0)
|
if(getblk(fs, l, b, si, &res->blk, GBWRITE) <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
res->deind = sj;
|
res->deind = sj;
|
||||||
|
res->Qid = (Qid){0, 0, 0};
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,9 @@ chanwalk(Chan *ch, char *name)
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
d = &b->de[ch->loc->deind];
|
d = getdent(ch->loc, b);
|
||||||
|
if(d == nil)
|
||||||
|
goto error;
|
||||||
if((d->type & QTDIR) == 0){
|
if((d->type & QTDIR) == 0){
|
||||||
werrstr(Enotadir);
|
werrstr(Enotadir);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -132,7 +134,9 @@ chancreat(Chan *ch, char *name, int perm, int mode)
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
d = &b->de[ch->loc->deind];
|
d = getdent(ch->loc, b);
|
||||||
|
if(d == nil)
|
||||||
|
goto error;
|
||||||
if((d->type & QTDIR) == 0){
|
if((d->type & QTDIR) == 0){
|
||||||
werrstr(Enotadir);
|
werrstr(Enotadir);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -146,9 +150,9 @@ chancreat(Chan *ch, char *name, int perm, int mode)
|
||||||
c = getbuf(ch->fs->d, f.blk, TDENTRY, 0);
|
c = getbuf(ch->fs->d, f.blk, TDENTRY, 0);
|
||||||
if(c == nil)
|
if(c == nil)
|
||||||
goto error;
|
goto error;
|
||||||
c->op |= BDELWRI;
|
|
||||||
b->op |= BDELWRI;
|
|
||||||
modified(ch, d);
|
modified(ch, d);
|
||||||
|
b->op |= BDELWRI;
|
||||||
|
c->op |= BDELWRI;
|
||||||
if(isdir)
|
if(isdir)
|
||||||
perm &= ~0777 | d->mode & 0777;
|
perm &= ~0777 | d->mode & 0777;
|
||||||
else
|
else
|
||||||
|
@ -213,7 +217,9 @@ chanopen(Chan *ch, int mode)
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
d = &b->de[ch->loc->deind];
|
d = getdent(ch->loc, b);
|
||||||
|
if(d == nil)
|
||||||
|
goto err;
|
||||||
if(!permcheck(ch->fs, d, ch->uid, mode & OEXEC)){
|
if(!permcheck(ch->fs, d, ch->uid, mode & OEXEC)){
|
||||||
permerr:
|
permerr:
|
||||||
werrstr(Eperm);
|
werrstr(Eperm);
|
||||||
|
@ -325,7 +331,12 @@ chanwrite(Chan *ch, void *buf, ulong n, uvlong off)
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
d = &b->de[ch->loc->deind];
|
d = getdent(ch->loc, b);
|
||||||
|
if(d == nil){
|
||||||
|
putbuf(b);
|
||||||
|
chend(ch);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if((d->type & QTAPPEND) != 0)
|
if((d->type & QTAPPEND) != 0)
|
||||||
off = d->size;
|
off = d->size;
|
||||||
e = off + n;
|
e = off + n;
|
||||||
|
@ -392,7 +403,12 @@ chanread(Chan *ch, void *buf, ulong n, uvlong off)
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
d = &b->de[ch->loc->deind];
|
d = getdent(ch->loc, b);
|
||||||
|
if(d == nil){
|
||||||
|
putbuf(b);
|
||||||
|
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)
|
||||||
|
@ -465,6 +481,7 @@ int
|
||||||
chanstat(Chan *ch, Dir *di)
|
chanstat(Chan *ch, Dir *di)
|
||||||
{
|
{
|
||||||
Buf *b;
|
Buf *b;
|
||||||
|
Dentry *d;
|
||||||
|
|
||||||
chbegin(ch);
|
chbegin(ch);
|
||||||
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
|
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
|
||||||
|
@ -472,7 +489,13 @@ chanstat(Chan *ch, Dir *di)
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
statbuf(ch->fs, &b->de[ch->loc->deind], di, nil);
|
d = getdent(ch->loc, b);
|
||||||
|
if(d == nil){
|
||||||
|
putbuf(b);
|
||||||
|
chend(ch);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
statbuf(ch->fs, d, di, nil);
|
||||||
putbuf(b);
|
putbuf(b);
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -504,7 +527,12 @@ chandirread(Chan *ch, void *buf, ulong n, uvlong off)
|
||||||
chend(ch);
|
chend(ch);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
d = &b->de[ch->loc->deind];
|
d = getdent(ch->loc, b);
|
||||||
|
if(d == nil){
|
||||||
|
putbuf(b);
|
||||||
|
chend(ch);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if(ch->dwblk >= d->size){
|
if(ch->dwblk >= d->size){
|
||||||
putbuf(b);
|
putbuf(b);
|
||||||
chend(ch);
|
chend(ch);
|
||||||
|
@ -590,11 +618,16 @@ chanclunk(Chan *ch)
|
||||||
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 err;
|
||||||
if(!permcheck(ch->fs, &p->de[ch->loc->next->deind], ch->uid, OWRITE)){
|
d = getdent(ch->loc->next, p);
|
||||||
|
if(d == nil)
|
||||||
|
goto err;
|
||||||
|
if(!permcheck(ch->fs, d, ch->uid, OWRITE)){
|
||||||
werrstr(Eperm);
|
werrstr(Eperm);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
d = &b->de[ch->loc->deind];
|
d = getdent(ch->loc, b);
|
||||||
|
if(d == nil)
|
||||||
|
goto err;
|
||||||
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)
|
||||||
|
@ -653,7 +686,10 @@ chanwstat(Chan *ch, Dir *di)
|
||||||
pb = getbuf(ch->fs->d, ch->loc->next->blk, TDENTRY, 0);
|
pb = getbuf(ch->fs->d, ch->loc->next->blk, TDENTRY, 0);
|
||||||
if(pb == nil)
|
if(pb == nil)
|
||||||
goto error;
|
goto error;
|
||||||
if(!permcheck(ch->fs, &pb->de[ch->loc->next->deind], ch->uid, OWRITE))
|
d = getdent(ch->loc->next, pb);
|
||||||
|
if(d == nil)
|
||||||
|
goto error;
|
||||||
|
if(!permcheck(ch->fs, d, ch->uid, OWRITE))
|
||||||
goto perm;
|
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)
|
||||||
|
@ -664,7 +700,9 @@ chanwstat(Chan *ch, Dir *di)
|
||||||
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 error;
|
goto error;
|
||||||
d = &b->de[ch->loc->deind];
|
d = getdent(ch->loc, b);
|
||||||
|
if(d == nil)
|
||||||
|
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;
|
||||||
if((uvlong)~di->length){
|
if((uvlong)~di->length){
|
||||||
|
|
Loading…
Reference in a new issue