summaryrefslogtreecommitdiff
path: root/sys/src/9/port/devswap.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2021-10-23 13:40:06 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2021-10-23 13:40:06 +0000
commitdb971a6189e63802b4c7c0ee41bf00e9864f52a7 (patch)
treeb211a3e5ae91db86a2099019e323eaeb2a63cb77 /sys/src/9/port/devswap.c
parente54b6c6cbd4d82d70ddb4932aeafb0b028cd71f5 (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/devswap.c')
-rw-r--r--sys/src/9/port/devswap.c17
1 files changed, 7 insertions, 10 deletions
diff --git a/sys/src/9/port/devswap.c b/sys/src/9/port/devswap.c
index fe872057e..d0d8156b9 100644
--- a/sys/src/9/port/devswap.c
+++ b/sys/src/9/port/devswap.c
@@ -383,10 +383,6 @@ needpages(void*)
static void
setswapchan(Chan *c)
{
- uchar buf[sizeof(Dir)+100];
- Dir d;
- int n;
-
if(waserror()){
cclose(c);
nexterror();
@@ -403,16 +399,17 @@ setswapchan(Chan *c)
* to be at most the size of the partition
*/
if(devtab[c->type]->dc != L'M'){
- n = devtab[c->type]->stat(c, buf, sizeof buf);
- if(n <= 0 || convM2D(buf, n, &d, nil) == 0)
- error("stat failed in setswapchan");
- if(d.length < (vlong)conf.nswppo*BY2PG)
+ Dir *d = dirchanstat(c);
+ if(d->length < (vlong)conf.nswppo*BY2PG){
+ free(d);
error("swap device too small");
- if(d.length < (vlong)conf.nswap*BY2PG){
- conf.nswap = d.length/BY2PG;
+ }
+ if(d->length < (vlong)conf.nswap*BY2PG){
+ conf.nswap = d->length/BY2PG;
swapalloc.top = &swapalloc.swmap[conf.nswap];
swapalloc.free = conf.nswap;
}
+ free(d);
}
c->flag &= ~CCACHE;
cclunk(c);