panic() cleanup.
[minix.git] / servers / mfs / protect.c
blob4a451d98616e3d2f9fa50a26720d842b24897ccd
1 #include "fs.h"
2 #include <unistd.h>
3 #include <minix/callnr.h>
4 #include "buf.h"
5 #include "inode.h"
6 #include "super.h"
7 #include <minix/vfsif.h>
9 FORWARD _PROTOTYPE( in_group, (gid_t grp) );
12 /*===========================================================================*
13 * fs_chmod *
14 *===========================================================================*/
15 PUBLIC int fs_chmod()
17 /* Perform the chmod(name, mode) system call. */
19 register struct inode *rip;
20 register int r;
22 /* Temporarily open the file. */
23 if( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
24 return(EINVAL);
26 /* Now make the change. Clear setgid bit if file is not in caller's grp */
27 rip->i_mode = (rip->i_mode & ~ALL_MODES) | (fs_m_in.REQ_MODE & ALL_MODES);
28 rip->i_update |= CTIME;
29 rip->i_dirt = DIRTY;
31 /* Return full new mode to caller. */
32 fs_m_out.RES_MODE = rip->i_mode;
34 put_inode(rip);
35 return(OK);
39 /*===========================================================================*
40 * fs_chown *
41 *===========================================================================*/
42 PUBLIC int fs_chown()
44 register struct inode *rip;
45 register int r;
47 /* Temporarily open the file. */
48 if( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
49 return(EINVAL);
51 /* Not permitted to change the owner of a file on a read-only file sys. */
52 r = read_only(rip);
53 if (r == OK) {
54 rip->i_uid = fs_m_in.REQ_UID;
55 rip->i_gid = fs_m_in.REQ_GID;
56 rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT);
57 rip->i_update |= CTIME;
58 rip->i_dirt = DIRTY;
61 /* Update caller on current mode, as it may have changed. */
62 fs_m_out.RES_MODE = rip->i_mode;
63 put_inode(rip);
65 return(r);
69 /*===========================================================================*
70 * forbidden *
71 *===========================================================================*/
72 PUBLIC int forbidden(register struct inode *rip, mode_t access_desired)
74 /* Given a pointer to an inode, 'rip', and the access desired, determine
75 * if the access is allowed, and if not why not. The routine looks up the
76 * caller's uid in the 'fproc' table. If access is allowed, OK is returned
77 * if it is forbidden, EACCES is returned.
80 register struct inode *old_rip = rip;
81 register struct super_block *sp;
82 register mode_t bits, perm_bits;
83 int r, shift;
85 /* Isolate the relevant rwx bits from the mode. */
86 bits = rip->i_mode;
87 if (caller_uid == SU_UID) {
88 /* Grant read and write permission. Grant search permission for
89 * directories. Grant execute permission (for non-directories) if
90 * and only if one of the 'X' bits is set.
92 if ( (bits & I_TYPE) == I_DIRECTORY ||
93 bits & ((X_BIT << 6) | (X_BIT << 3) | X_BIT))
94 perm_bits = R_BIT | W_BIT | X_BIT;
95 else
96 perm_bits = R_BIT | W_BIT;
97 } else {
98 if (caller_uid == rip->i_uid) shift = 6; /* owner */
99 else if (caller_gid == rip->i_gid) shift = 3; /* group */
100 else if (in_group(rip->i_gid) == OK) shift = 3; /* other groups */
101 else shift = 0; /* other */
102 perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
105 /* If access desired is not a subset of what is allowed, it is refused. */
106 r = OK;
107 if ((perm_bits | access_desired) != perm_bits) r = EACCES;
109 /* Check to see if someone is trying to write on a file system that is
110 * mounted read-only.
112 if (r == OK)
113 if (access_desired & W_BIT)
114 r = read_only(rip);
116 if (rip != old_rip) put_inode(rip);
118 return(r);
122 /*===========================================================================*
123 * in_group *
124 *===========================================================================*/
125 PRIVATE int in_group(gid_t grp)
127 int i;
128 for(i = 0; i < credentials.vu_ngroups; i++)
129 if (credentials.vu_sgroups[i] == grp)
130 return(OK);
132 return(EINVAL);
136 /*===========================================================================*
137 * read_only *
138 *===========================================================================*/
139 PUBLIC int read_only(ip)
140 struct inode *ip; /* ptr to inode whose file sys is to be cked */
142 /* Check to see if the file system on which the inode 'ip' resides is mounted
143 * read only. If so, return EROFS, else return OK.
146 register struct super_block *sp;
148 sp = ip->i_sp;
149 return(sp->s_rd_only ? EROFS : OK);