1 /* This file contains file metadata retrieval and manipulation routines.
3 * The entry points into this file are:
4 * get_mode return a file's mode
5 * do_stat perform the STAT file system call
6 * do_chmod perform the CHMOD file system call
7 * do_utime perform the UTIME file system call
10 * April 2009 (D.C. van Moolenbroek)
15 /*===========================================================================*
17 *===========================================================================*/
18 mode_t
get_mode(ino
, mode
)
22 /* Return the mode for an inode, given the inode and the retrieved mode.
26 mode
= mode
| (mode
>> 3) | (mode
>> 6);
29 mode
= S_IFDIR
| (mode
& sffs_params
->p_dir_mask
);
31 mode
= S_IFREG
| (mode
& sffs_params
->p_file_mask
);
33 if (state
.s_read_only
)
34 mode
&= ~(S_IWUSR
| S_IWGRP
| S_IWOTH
);
39 /*===========================================================================*
41 *===========================================================================*/
44 /* Retrieve inode status.
47 struct sffs_attr attr
;
53 ino_nr
= m_in
.REQ_INODE_NR
;
55 /* Don't increase the inode refcount: it's already open anyway */
56 if ((ino
= find_inode(ino_nr
)) == NULL
)
59 attr
.a_mask
= SFFS_ATTR_MODE
| SFFS_ATTR_SIZE
| SFFS_ATTR_CRTIME
|
60 SFFS_ATTR_ATIME
| SFFS_ATTR_MTIME
| SFFS_ATTR_CTIME
;
62 if ((r
= verify_inode(ino
, path
, &attr
)) != OK
)
65 memset(&stat
, 0, sizeof(struct stat
));
67 stat
.st_dev
= state
.s_dev
;
69 stat
.st_mode
= get_mode(ino
, attr
.a_mode
);
70 stat
.st_uid
= sffs_params
->p_uid
;
71 stat
.st_gid
= sffs_params
->p_gid
;
72 stat
.st_rdev
= NO_DEV
;
73 if (cmp64u(attr
.a_size
, LONG_MAX
) > 0)
74 stat
.st_size
= LONG_MAX
;
76 stat
.st_size
= ex64lo(attr
.a_size
);
77 stat
.st_atimespec
= attr
.a_atime
;
78 stat
.st_mtimespec
= attr
.a_mtime
;
79 stat
.st_ctimespec
= attr
.a_ctime
;
80 stat
.st_birthtimespec
= attr
.a_crtime
;
82 stat
.st_blocks
= stat
.st_size
/ S_BLKSIZE
;
83 if (stat
.st_size
% S_BLKSIZE
!= 0)
86 stat
.st_blksize
= BLOCK_SIZE
;
88 /* We could make this more accurate by iterating over directory inodes'
89 * children, counting how many of those are directories as well.
90 * It's just not worth it.
93 if (ino
->i_parent
!= NULL
) stat
.st_nlink
++;
96 if (HAS_CHILDREN(ino
)) stat
.st_nlink
++;
99 return sys_safecopyto(m_in
.m_source
, m_in
.REQ_GRANT
, 0,
100 (vir_bytes
) &stat
, sizeof(stat
));
103 /*===========================================================================*
105 *===========================================================================*/
112 struct sffs_attr attr
;
115 if (state
.s_read_only
)
118 if ((ino
= find_inode(m_in
.REQ_INODE_NR
)) == NULL
)
121 if ((r
= verify_inode(ino
, path
, NULL
)) != OK
)
124 /* Set the new file mode. */
125 attr
.a_mask
= SFFS_ATTR_MODE
;
126 attr
.a_mode
= m_in
.REQ_MODE
; /* no need to convert in this direction */
128 if ((r
= sffs_table
->t_setattr(path
, &attr
)) != OK
)
131 /* We have no idea what really happened. Query for the mode again. */
132 if ((r
= verify_path(path
, ino
, &attr
, NULL
)) != OK
)
135 m_out
.RES_MODE
= get_mode(ino
, attr
.a_mode
);
140 /*===========================================================================*
142 *===========================================================================*/
149 struct sffs_attr attr
;
152 if (state
.s_read_only
)
155 if ((ino
= find_inode(m_in
.REQ_INODE_NR
)) == NULL
)
158 if ((r
= verify_inode(ino
, path
, NULL
)) != OK
)
161 attr
.a_mask
= SFFS_ATTR_ATIME
| SFFS_ATTR_MTIME
;
162 attr
.a_atime
.tv_sec
= m_in
.REQ_ACTIME
;
163 attr
.a_atime
.tv_nsec
= 0;
164 attr
.a_mtime
.tv_sec
= m_in
.REQ_MODTIME
;
165 attr
.a_mtime
.tv_nsec
= 0;
167 return sffs_table
->t_setattr(path
, &attr
);