1 /* Created (MFS based):
2 * February 2010 (Evgeniy Ivanov)
8 #include <minix/vfsif.h>
10 static int in_group(gid_t grp
);
13 /*===========================================================================*
15 *===========================================================================*/
18 /* Perform the chmod(name, mode) system call. */
20 register struct inode
*rip
;
23 mode
= (mode_t
) fs_m_in
.REQ_MODE
;
25 /* Temporarily open the file. */
26 if( (rip
= get_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
)) == NULL
)
29 /* Now make the change. Clear setgid bit if file is not in caller's grp */
30 rip
->i_mode
= (rip
->i_mode
& ~ALL_MODES
) | (mode
& ALL_MODES
);
31 rip
->i_update
|= CTIME
;
32 rip
->i_dirt
= IN_DIRTY
;
34 /* Return full new mode to caller. */
35 fs_m_out
.RES_MODE
= rip
->i_mode
;
42 /*===========================================================================*
44 *===========================================================================*/
47 register struct inode
*rip
;
50 /* Temporarily open the file. */
51 if( (rip
= get_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
)) == NULL
)
54 /* Not permitted to change the owner of a file on a read-only file sys. */
57 rip
->i_uid
= fs_m_in
.REQ_UID
;
58 rip
->i_gid
= fs_m_in
.REQ_GID
;
59 rip
->i_mode
&= ~(I_SET_UID_BIT
| I_SET_GID_BIT
);
60 rip
->i_update
|= CTIME
;
61 rip
->i_dirt
= IN_DIRTY
;
64 /* Update caller on current mode, as it may have changed. */
65 fs_m_out
.RES_MODE
= rip
->i_mode
;
72 /*===========================================================================*
74 *===========================================================================*/
75 int forbidden(register struct inode
*rip
, mode_t access_desired
)
77 /* Given a pointer to an inode, 'rip', and the access desired, determine
78 * if the access is allowed, and if not why not. The routine looks up the
79 * caller's uid in the 'fproc' table. If access is allowed, OK is returned
80 * if it is forbidden, EACCES is returned.
83 register struct inode
*old_rip
= rip
;
84 register mode_t bits
, perm_bits
;
87 /* Isolate the relevant rwx bits from the mode. */
89 if (caller_uid
== SU_UID
) {
90 /* Grant read and write permission. Grant search permission for
91 * directories. Grant execute permission (for non-directories) if
92 * and only if one of the 'X' bits is set.
94 if ( (bits
& I_TYPE
) == I_DIRECTORY
||
95 bits
& ((X_BIT
<< 6) | (X_BIT
<< 3) | X_BIT
))
96 perm_bits
= R_BIT
| W_BIT
| X_BIT
;
98 perm_bits
= R_BIT
| W_BIT
;
100 if (caller_uid
== rip
->i_uid
) shift
= 6; /* owner */
101 else if (caller_gid
== rip
->i_gid
) shift
= 3; /* group */
102 else if (in_group(rip
->i_gid
) == OK
) shift
= 3; /* other groups */
103 else shift
= 0; /* other */
104 perm_bits
= (bits
>> shift
) & (R_BIT
| W_BIT
| X_BIT
);
107 /* If access desired is not a subset of what is allowed, it is refused. */
109 if ((perm_bits
| access_desired
) != perm_bits
) r
= EACCES
;
111 /* Check to see if someone is trying to write on a file system that is
115 if (access_desired
& W_BIT
) {
120 if (rip
!= old_rip
) put_inode(rip
);
126 /*===========================================================================*
128 *===========================================================================*/
129 static int in_group(gid_t grp
)
133 if (credentials
.vu_ngroups
> NGROUPS_MAX
)
136 for (i
= 0; i
< credentials
.vu_ngroups
; i
++)
137 if (credentials
.vu_sgroups
[i
] == grp
)
144 /*===========================================================================*
146 *===========================================================================*/
148 struct inode
*ip
; /* ptr to inode whose file sys is to be cked */
150 /* Check to see if the file system on which the inode 'ip' resides is mounted
151 * read only. If so, return EROFS, else return OK.
154 register struct super_block
*sp
;
157 return(sp
->s_rd_only
? EROFS
: OK
);