5 #include <minix/callnr.h>
10 #include <minix/vfsif.h>
13 /*===========================================================================*
15 *===========================================================================*/
18 /* Perform the chmod(name, mode) system call. */
20 register struct inode
*rip
;
23 caller_uid
= fs_m_in
.REQ_UID
;
24 caller_gid
= fs_m_in
.REQ_GID
;
26 /* Temporarily open the file. */
27 if ( (rip
= get_inode(fs_dev
, fs_m_in
.REQ_INODE_NR
)) == NIL_INODE
) {
28 printf("MFS(%d) get_inode by fs_chmod() failed\n", SELF_E
);
32 /* Only the owner or the super_user may change the mode of a file.
33 * No one may change the mode of a file on a read-only file system.
35 if (rip
->i_uid
!= caller_uid
&& caller_uid
!= SU_UID
)
40 /* If error, return inode. */
46 /* Now make the change. Clear setgid bit if file is not in caller's grp */
47 rip
->i_mode
= (rip
->i_mode
& ~ALL_MODES
) | (fs_m_in
.REQ_MODE
& ALL_MODES
);
48 if (caller_uid
!= SU_UID
&& rip
->i_gid
!= caller_gid
)
49 rip
->i_mode
&= ~I_SET_GID_BIT
;
50 rip
->i_update
|= CTIME
;
53 /* Return full new mode to caller. */
54 fs_m_out
.RES_MODE
= rip
->i_mode
;
61 /*===========================================================================*
63 *===========================================================================*/
66 register struct inode
*rip
;
68 /* Temporarily open the file. */
69 caller_uid
= fs_m_in
.REQ_UID
;
70 caller_gid
= fs_m_in
.REQ_GID
;
72 /* Temporarily open the file. */
73 if ( (rip
= get_inode(fs_dev
, fs_m_in
.REQ_INODE_NR
)) == NIL_INODE
) {
74 printf("MFS(%d) get_inode by fs_chown() failed\n", SELF_E
);
78 /* Not permitted to change the owner of a file on a read-only file sys. */
81 /* FS is R/W. Whether call is allowed depends on ownership, etc. */
82 if (caller_uid
== SU_UID
) {
83 /* The super user can do anything. */
84 rip
->i_uid
= fs_m_in
.REQ_NEW_UID
; /* others later */
86 /* Regular users can only change groups of their own files. */
87 if (rip
->i_uid
!= caller_uid
) r
= EPERM
;
88 if (rip
->i_uid
!= fs_m_in
.REQ_NEW_UID
)
89 r
= EPERM
; /* no giving away */
90 if (caller_gid
!= fs_m_in
.REQ_NEW_GID
) r
= EPERM
;
94 rip
->i_gid
= fs_m_in
.REQ_NEW_GID
;
95 rip
->i_mode
&= ~(I_SET_UID_BIT
| I_SET_GID_BIT
);
96 rip
->i_update
|= CTIME
;
100 /* Update caller on current mode, as it may have changed. */
101 fs_m_out
.RES_MODE
= rip
->i_mode
;
108 /*===========================================================================*
110 *===========================================================================*/
111 PUBLIC
int fs_access()
116 /* Temporarily open the file whose access is to be checked. */
117 caller_uid
= fs_m_in
.REQ_UID
;
118 caller_gid
= fs_m_in
.REQ_GID
;
120 /* Temporarily open the file. */
121 if ( (rip
= get_inode(fs_dev
, fs_m_in
.REQ_INODE_NR
)) == NIL_INODE
) {
122 printf("MFS(%d) get_inode by fs_access() failed\n", SELF_E
);
126 /* Now check the permissions. */
127 r
= forbidden(rip
, (mode_t
) fs_m_in
.REQ_MODE
);
132 /*===========================================================================*
134 *===========================================================================*/
135 PUBLIC
int forbidden(register struct inode
*rip
, mode_t access_desired
)
137 /* Given a pointer to an inode, 'rip', and the access desired, determine
138 * if the access is allowed, and if not why not. The routine looks up the
139 * caller's uid in the 'fproc' table. If access is allowed, OK is returned
140 * if it is forbidden, EACCES is returned.
143 register struct inode
*old_rip
= rip
;
144 register struct super_block
*sp
;
145 register mode_t bits
, perm_bits
;
149 if (rip->i_mount == I_MOUNT)
150 for (sp = &super_block[1]; sp < &super_block[NR_SUPERS]; sp++)
151 if (sp->s_imount == rip) {
152 rip = get_inode(sp->s_dev, ROOT_INODE);
157 /* Isolate the relevant rwx bits from the mode. */
159 if (caller_uid
== SU_UID
) {
160 /* Grant read and write permission. Grant search permission for
161 * directories. Grant execute permission (for non-directories) if
162 * and only if one of the 'X' bits is set.
164 if ( (bits
& I_TYPE
) == I_DIRECTORY
||
165 bits
& ((X_BIT
<< 6) | (X_BIT
<< 3) | X_BIT
))
166 perm_bits
= R_BIT
| W_BIT
| X_BIT
;
168 perm_bits
= R_BIT
| W_BIT
;
170 if (caller_uid
== rip
->i_uid
) shift
= 6; /* owner */
171 else if (caller_gid
== rip
->i_gid
) shift
= 3; /* group */
172 else shift
= 0; /* other */
173 perm_bits
= (bits
>> shift
) & (R_BIT
| W_BIT
| X_BIT
);
176 /* If access desired is not a subset of what is allowed, it is refused. */
178 if ((perm_bits
| access_desired
) != perm_bits
) r
= EACCES
;
180 /* Check to see if someone is trying to write on a file system that is
183 type
= rip
->i_mode
& I_TYPE
;
185 if (access_desired
& W_BIT
)
188 if (rip
!= old_rip
) put_inode(rip
);
190 /*printf("FSforbidden: %s %s\n", user_path, (r == OK ? "OK" : "notOK")); */
194 /*===========================================================================*
196 *===========================================================================*/
197 PUBLIC
int read_only(ip
)
198 struct inode
*ip
; /* ptr to inode whose file sys is to be cked */
200 /* Check to see if the file system on which the inode 'ip' resides is mounted
201 * read only. If so, return EROFS, else return OK.
204 register struct super_block
*sp
;
207 return(sp
->s_rd_only
? EROFS
: OK
);