From 5eb938b070d914fe663c3ffb41505e4f10c9e294 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 20 Feb 2015 20:45:25 +0000 Subject: [PATCH] readonly: Initial pieces for read-only mounts --- Kernel/filesys.c | 28 +++++++++++++++++++++++++--- Kernel/include/kernel.h | 3 ++- Kernel/syscall_fs2.c | 35 +++++++++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/Kernel/filesys.c b/Kernel/filesys.c index 490c9694..dc95386e 100644 --- a/Kernel/filesys.c +++ b/Kernel/filesys.c @@ -187,6 +187,7 @@ inoptr i_open(uint16_t dev, uint16_t ino) { struct dinode *buf; inoptr nindex, j; + struct mount *m; bool isnew = false; if(!validdev(dev)) @@ -201,9 +202,11 @@ inoptr i_open(uint16_t dev, uint16_t ino) } } + m = fs_tab_get(dev); + /* Maybe make this DEBUG only eventually - the fs_tab_get cost is higher than ideal */ - if(ino < ROOTINODE || ino >= (fs_tab_get(dev)->m_fs->s_isize - 2) * 8) { + if(ino < ROOTINODE || ino >= (m->m_fs->s_isize - 2) * 8) { kputs("i_open: bad inode number\n"); return NULLINODE; } @@ -232,7 +235,7 @@ inoptr i_open(uint16_t dev, uint16_t ino) nindex->c_dev = dev; nindex->c_num = ino; nindex->c_magic = CMAGIC; - + nindex->c_flags = (m->m_flags & MS_RDONLY) ? CRDONLY : 0; found: if(isnew) { if(nindex->c_node.i_nlink || nindex->c_node.i_mode & F_MASK) @@ -265,6 +268,10 @@ bool ch_link(inoptr wd, char *oldname, char *newname, inoptr nindex) struct direct curentry; int i; + if (wd->c_flags & CRDONLY) { + udata.u_error = EROFS; + return false; + } if(!(getperm(wd) & OTH_WR)) { udata.u_error = EPERM; @@ -394,6 +401,11 @@ inoptr newfile(inoptr pino, char *name) uint8_t j; /* First see if parent is writeable */ + if (pino->c_flags & CRDONLY) { + udata.u_error = EROFS; + goto nogood; + } + if(!(getperm(pino) & OTH_WR)) goto nogood; @@ -468,6 +480,7 @@ uint16_t i_alloc(uint16_t devno) { staticfast fsptr dev; staticfast blkno_t blk; + staticfast struct mount *m; struct dinode *buf; staticfast uint16_t j; uint16_t k; @@ -475,6 +488,7 @@ uint16_t i_alloc(uint16_t devno) if(baddev(dev = getdev(devno))) goto corrupt; + m = fs_tab_get(devno); tryagain: if(dev->s_ninode) { @@ -800,11 +814,15 @@ uint16_t devnum(inoptr ino) /* F_trunc frees all the blocks associated with the file, if it * is a disk file. */ -void f_trunc(inoptr ino) +int f_trunc(inoptr ino) { uint16_t dev; int8_t j; + if (ino->c_flags & CRDONLY) { + udata.u_error = EROFS; + return -1; + } dev = ino->c_dev; /* First deallocate the double indirect blocks */ @@ -821,6 +839,7 @@ void f_trunc(inoptr ino) ino->c_flags |= CDIRTY; ino->c_node.i_size = 0; + return 0; } @@ -1015,6 +1034,9 @@ uint8_t getperm(inoptr ino) */ void setftime(inoptr ino, uint8_t flag) { + if (ino->c_flags & CRDONLY) + return; + ino->c_flags |= CDIRTY; if(flag & A_TIME) diff --git a/Kernel/include/kernel.h b/Kernel/include/kernel.h index a5f623f6..a87240a1 100644 --- a/Kernel/include/kernel.h +++ b/Kernel/include/kernel.h @@ -191,6 +191,7 @@ typedef struct cinode { // note: exists in memory *and* on disk uint8_t c_refs; /* In-core reference count */ uint8_t c_flags; #define CDIRTY 0x80 /* Modified flag. */ +#define CRDONLY 0x40 /* On a read only file system */ #define CFLOCK 0x0F /* flock bits */ #define CFLEX 0x0F /* locked exclusive */ #define CFMAX 0x0E /* highest shared lock count permitted */ @@ -672,7 +673,7 @@ extern void i_ref(inoptr ino); extern void i_deref(inoptr ino); extern void wr_inode(inoptr ino); extern bool isdevice(inoptr ino); -extern void f_trunc(inoptr ino); +extern int f_trunc(inoptr ino); extern void freeblk(uint16_t dev, blkno_t blk, uint8_t level); extern blkno_t bmap(inoptr ip, blkno_t bn, int rwflg); extern void validblk(uint16_t dev, blkno_t num); diff --git a/Kernel/syscall_fs2.c b/Kernel/syscall_fs2.c index b96656ff..23ea0365 100644 --- a/Kernel/syscall_fs2.c +++ b/Kernel/syscall_fs2.c @@ -186,6 +186,10 @@ static arg_t chmod_op(inoptr ino) { if (ino->c_node.i_uid != udata.u_euid && esuper()) return (-1); + if (ino->c_flags & CRDONLY) { + udata.u_error = EROFS; + return -1; + } ino->c_node.i_mode = (mode & MODE_MASK) | (ino->c_node.i_mode & F_MASK); @@ -242,6 +246,10 @@ static int chown_op(inoptr ino) { if (ino->c_node.i_uid != udata.u_euid && esuper()) return (-1); + if (ino->c_flags & CRDONLY) { + udata.u_error = EROFS; + return -1; + } ino->c_node.i_uid = owner; ino->c_node.i_gid = group; setftime(ino, C_TIME); @@ -308,6 +316,10 @@ arg_t _utime(void) if (!(ino = n_open(file, NULLINOPTR))) return (-1); + if (ino->c_flags & CRDONLY) { + udata.u_error = EROFS; + goto out2; + } /* Special case in the Unix API - NULL means now */ if (buf) { if (ino->c_node.i_uid != udata.u_euid && esuper()) @@ -363,6 +375,10 @@ arg_t _acct(void) udata.u_error = EINVAL; return -1; } + if (ino->c_flags & CRDONLY) { + udata.u_error = EROFS; + return -1; + } acct_fh = udata.u_files[fd]; ++of_tab[acct_fh].o_refs; } @@ -473,11 +489,17 @@ arg_t _open(void) perm = getperm(ino); if ((r && !(perm & OTH_RD)) || (w && !(perm & OTH_WR))) { udata.u_error = EPERM; - goto cantopen; + goto idrop; } - if (getmode(ino) == F_DIR && w) { - udata.u_error = EISDIR; - goto cantopen; + if (w) { + if (getmode(ino) == F_DIR ) { + udata.u_error = EISDIR; + goto idrop; + } + if (ino->c_flags & CRDONLY) { + udata.u_error = EROFS; + goto idrop; + } } itmp = ino; /* d_open may block and thus ino may become invalid as may @@ -485,12 +507,13 @@ arg_t _open(void) if (isdevice(ino) && d_open((int) ino->c_node.i_addr[0], flag) != 0) { udata.u_error = ENXIO; - goto cantopen; + goto idrop; } /* get the static pointer back */ ino = itmp; if (trunc && getmode(ino) == F_REG) { - f_trunc(ino); + if (f_trunc(ino)) + goto idrop; for (j = 0; j < OFTSIZE; ++j) /* Arguably should fix at read/write */ if (of_tab[j].o_inode == ino) -- 2.34.1