1 /* Created (MFS based):
2 * June 2011 (Evgeniy Ivanov)
6 #include <minix/vfsif.h>
9 #include "puffs_priv.h"
11 static int in_group(gid_t grp
);
14 /*===========================================================================*
16 *===========================================================================*/
19 /* Perform the chmod(name, mode) system call. */
20 struct puffs_node
*pn
;
23 PUFFS_MAKECRED(pcr
, &global_kcred
);
25 if (global_pu
->pu_ops
.puffs_node_setattr
== NULL
)
28 mode
= (mode_t
) fs_m_in
.REQ_MODE
;
30 if ((pn
= puffs_pn_nodewalk(global_pu
, 0, &fs_m_in
.REQ_INODE_NR
)) == NULL
)
33 puffs_vattr_null(&va
);
34 /* Clear setgid bit if file is not in caller's grp */
35 va
.va_mode
= (pn
->pn_va
.va_mode
& ~ALL_MODES
) | (mode
& ALL_MODES
);
36 va
.va_ctime
.tv_nsec
= 0;
37 va
.va_ctime
.tv_sec
= clock_time();
39 if (global_pu
->pu_ops
.puffs_node_setattr(global_pu
, pn
, &va
, pcr
) != 0)
42 /* Return full new mode to caller. */
43 fs_m_out
.RES_MODE
= pn
->pn_va
.va_mode
;
49 /*===========================================================================*
51 *===========================================================================*/
54 struct puffs_node
*pn
;
56 PUFFS_MAKECRED(pcr
, &global_kcred
);
58 if ((pn
= puffs_pn_nodewalk(global_pu
, 0, &fs_m_in
.REQ_INODE_NR
)) == NULL
)
61 /* Not permitted to change the owner of a file on a read-only file sys. */
62 if (!is_readonly_fs
) {
63 puffs_vattr_null(&va
);
64 va
.va_uid
= fs_m_in
.REQ_UID
;
65 va
.va_gid
= fs_m_in
.REQ_GID
;
66 va
.va_mode
= pn
->pn_va
.va_mode
& ~(I_SET_UID_BIT
| I_SET_GID_BIT
);
67 va
.va_ctime
.tv_nsec
= 0;
68 va
.va_ctime
.tv_sec
= clock_time();
70 if (global_pu
->pu_ops
.puffs_node_setattr(global_pu
, pn
, &va
, pcr
) != 0)
74 /* Update caller on current mode, as it may have changed. */
75 fs_m_out
.RES_MODE
= pn
->pn_va
.va_mode
;
81 /*===========================================================================*
83 *===========================================================================*/
84 int forbidden(register struct puffs_node
*pn
, mode_t access_desired
)
86 /* Given a pointer to an pnode, 'pn', and the access desired, determine
87 * if the access is allowed, and if not why not. The routine looks up the
88 * caller's uid in the 'fproc' table. If access is allowed, OK is returned
89 * if it is forbidden, EACCES is returned.
92 register mode_t bits
, perm_bits
;
95 /* Isolate the relevant rwx bits from the mode. */
96 bits
= pn
->pn_va
.va_mode
;
97 if (caller_uid
== SU_UID
) {
98 /* Grant read and write permission. Grant search permission for
99 * directories. Grant execute permission (for non-directories) if
100 * and only if one of the 'X' bits is set.
102 if ( (bits
& I_TYPE
) == I_DIRECTORY
||
103 bits
& ((X_BIT
<< 6) | (X_BIT
<< 3) | X_BIT
))
104 perm_bits
= R_BIT
| W_BIT
| X_BIT
;
106 perm_bits
= R_BIT
| W_BIT
;
108 if (caller_uid
== pn
->pn_va
.va_uid
) shift
= 6; /* owner */
109 else if (caller_gid
== pn
->pn_va
.va_gid
) shift
= 3; /* group */
110 else if (in_group(pn
->pn_va
.va_gid
) == OK
) shift
= 3; /* other groups */
111 else shift
= 0; /* other */
112 perm_bits
= (bits
>> shift
) & (R_BIT
| W_BIT
| X_BIT
);
115 /* If access desired is not a subset of what is allowed, it is refused. */
117 if ((perm_bits
| access_desired
) != perm_bits
) r
= EACCES
;
119 /* Check to see if someone is trying to write on a file system that is
123 if (access_desired
& W_BIT
) {
124 r
= is_readonly_fs
? EROFS
: OK
;
132 /*===========================================================================*
134 *===========================================================================*/
135 static int in_group(gid_t grp
)
138 for(i
= 0; i
< credentials
.vu_ngroups
; i
++)
139 if (credentials
.vu_sgroups
[i
] == grp
)