#include "fs.h"
+#include "inode.h"
/*===========================================================================*
return(OK); /* sync() can't fail */
}
+
+/*===========================================================================*
+ * fs_chmod *
+ *===========================================================================*/
+int fs_chmod(message *fs_m_in, message *fs_m_out)
+{
+ struct inode *rip; /* target inode */
+ mode_t mode = (mode_t) fs_m_in->REQ_MODE;
+
+ if( (rip = find_inode(fs_m_in->REQ_INODE_NR)) == NULL) return(EINVAL);
+ get_inode(rip->i_dev, rip->i_num); /* mark inode in use */
+ rip->i_mode = (rip->i_mode & ~ALL_MODES) | (mode & ALL_MODES);
+ put_inode(rip); /* release the inode */
+ return OK;
+}
/* misc.c */
int fs_sync(message *fs_m_in, message *fs_m_out);
+int fs_chmod(message *fs_m_in, message *fs_m_out);
/* mount.c */
int fs_unmount(message *fs_m_in, message *fs_m_out);
no_sys, /* 3 */
fs_ftrunc, /* 4 */
no_sys, /* 5 */
- no_sys, /* 6 */
+ fs_chmod, /* 6 */
no_sys, /* 7 */
fs_stat, /* 8 */
no_sys, /* 9 */
#include "fs.h"
#include <sys/stat.h>
#include <unistd.h>
+#include <assert.h>
#include <minix/callnr.h>
#include "file.h"
#include "fproc.h"
/* File is already opened; get a pointer to vnode from filp. */
if ((flp = get_filp(rfd, VNODE_WRITE)) == NULL) return(err_code);
vp = flp->filp_vno;
+ assert(vp);
dup_vnode(vp);
}
+ assert(vp);
+
/* Only the owner or the super_user may change the mode of a file.
* No one may change the mode of a file on a read-only file system.
*/
/* Check to see if the file system on which the inode 'ip' resides is mounted
* read only. If so, return EROFS, else return OK.
*/
- return((vp->v_vmnt->m_flags & VMNT_READONLY) ? EROFS : OK);
+ assert(vp);
+ return(vp->v_vmnt && (vp->v_vmnt->m_flags & VMNT_READONLY) ? EROFS : OK);
}
}
+void test_fchmod()
+{
+ int socks[2];
+ struct stat st1, st2;
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) < 0) {
+ test_fail("Can't open socket pair.");
+ }
+
+ if (fstat(socks[0], &st1) < 0 || fstat(socks[1], &st2) < 0) {
+ test_fail("fstat failed.");
+ }
+
+ if ((st1.st_mode & (S_IRUSR|S_IWUSR)) == S_IRUSR &&
+ (st2.st_mode & (S_IRUSR|S_IWUSR)) == S_IWUSR) {
+ test_fail("fstat failed.");
+ }
+
+ if (fchmod(socks[0], S_IRUSR) < 0 ||
+ fstat(socks[0], &st1) < 0 ||
+ (st1.st_mode & (S_IRUSR|S_IWUSR)) != S_IRUSR) {
+ test_fail("fchmod/fstat mode set/check failed (1).");
+ }
+
+ if (fchmod(socks[1], S_IWUSR) < 0 || fstat(socks[1], &st2) < 0 ||
+ (st2.st_mode & (S_IRUSR|S_IWUSR)) != S_IWUSR) {
+ test_fail("fchmod/fstat mode set/check failed (2).");
+ }
+
+ close(socks[0]);
+ close(socks[1]);
+}
+
int main(int argc, char *argv[])
{
int i;
test_scm_credentials();
test_fd_passing();
test_select();
+ test_fchmod();
quit();
return -1; /* we should never get here */