{
struct dinode *buf;
inoptr nindex, j;
+ struct mount *m;
bool isnew = false;
if(!validdev(dev))
}
}
+ 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;
}
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)
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;
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;
{
staticfast fsptr dev;
staticfast blkno_t blk;
+ staticfast struct mount *m;
struct dinode *buf;
staticfast uint16_t j;
uint16_t k;
if(baddev(dev = getdev(devno)))
goto corrupt;
+ m = fs_tab_get(devno);
tryagain:
if(dev->s_ninode) {
/* 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 */
ino->c_flags |= CDIRTY;
ino->c_node.i_size = 0;
+ return 0;
}
*/
void setftime(inoptr ino, uint8_t flag)
{
+ if (ino->c_flags & CRDONLY)
+ return;
+
ino->c_flags |= CDIRTY;
if(flag & A_TIME)
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 */
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);
{
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);
{
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);
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())
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;
}
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
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)