diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2021-10-23 13:40:06 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2021-10-23 13:40:06 +0000 |
commit | db971a6189e63802b4c7c0ee41bf00e9864f52a7 (patch) | |
tree | b211a3e5ae91db86a2099019e323eaeb2a63cb77 /sys/src/9/port/devfs.c | |
parent | e54b6c6cbd4d82d70ddb4932aeafb0b028cd71f5 (diff) |
kernel: fix stat bugs
In a few places, we where using a fixed buffer of sizeof(Dir)+100
size for stat. This is not correct and fails if the name returned
in stat is long.
This results in being unable to seek to the end of file with a
long filename.
The kernel should do the same thing as dirfstat() from libc;
handling the conversion and buffer allocation and returning a
freeable Dir* pointer.
For this, a new dirchanstat() function was added.
The fstat syscall was not rewriting the name to the last path
element; fix it.
In addition, gracefully handle the mountfix case, reallocating
the buffer to accomidate the required stat length plus
size of the new name so dirsetname() does not fail.
Diffstat (limited to 'sys/src/9/port/devfs.c')
-rw-r--r-- | sys/src/9/port/devfs.c | 25 |
1 files changed, 8 insertions, 17 deletions
diff --git a/sys/src/9/port/devfs.c b/sys/src/9/port/devfs.c index 4a75f9c76..3607069b2 100644 --- a/sys/src/9/port/devfs.c +++ b/sys/src/9/port/devfs.c @@ -553,18 +553,6 @@ parsename(char *name, char *disk, char **tree, char **dev) validname(*dev, 0); } -static vlong -getlen(Chan *c) -{ - uchar buf[128]; /* old DIRLEN plus a little should be plenty */ - Dir d; - long l; - - l = devtab[c->type]->stat(c, buf, sizeof buf); - convM2D(buf, l, &d, nil); - return d.length; -} - /* * Process a single line of configuration, * often of the form "cmd newname idev0 idev1". @@ -602,8 +590,6 @@ mconfig(char* a, long n) start = 0; mp = nil; cb = nil; - idev = nil; - ilen = nil; keylen = 0; if(waserror()){ @@ -686,6 +672,8 @@ mconfig(char* a, long n) */ poperror(); rlock(&lck); + idev = smalloc(sizeof(Chan*) * Ndevs); + ilen = smalloc(sizeof(vlong) * Ndevs); if(waserror()){ runlock(&lck); Fail: @@ -699,11 +687,14 @@ Fail: free(cb); nexterror(); } - idev = smalloc(sizeof(Chan*) * Ndevs); - ilen = smalloc(sizeof(vlong) * Ndevs); for(i = 1; i < cb->nf; i++){ + Dir *dir; + idev[i-1] = namec(cb->f[i], Aopen, ORDWR, 0); - ilen[i-1] = getlen(idev[i-1]); + + dir = dirchanstat(idev[i-1]); + ilen[i-1] = dir->length; + free(dir); } poperror(); runlock(&lck); |