xref: /minix3/minix/lib/libsffs/stat.c (revision 7c48de6cc4c6d56f2277d378dba01dbac8a8c3b9)
1433d6423SLionel Sambuc /* This file contains file metadata retrieval and manipulation routines.
2433d6423SLionel Sambuc  *
3433d6423SLionel Sambuc  * The entry points into this file are:
4433d6423SLionel Sambuc  *   get_mode		return a file's mode
5433d6423SLionel Sambuc  *   do_stat		perform the STAT file system call
6433d6423SLionel Sambuc  *   do_chmod		perform the CHMOD file system call
7433d6423SLionel Sambuc  *   do_utime		perform the UTIME file system call
8433d6423SLionel Sambuc  *
9433d6423SLionel Sambuc  * Created:
10433d6423SLionel Sambuc  *   April 2009 (D.C. van Moolenbroek)
11433d6423SLionel Sambuc  */
12433d6423SLionel Sambuc 
13433d6423SLionel Sambuc #include "inc.h"
14433d6423SLionel Sambuc 
15433d6423SLionel Sambuc /*===========================================================================*
16433d6423SLionel Sambuc  *				get_mode				     *
17433d6423SLionel Sambuc  *===========================================================================*/
get_mode(struct inode * ino,int mode)18433d6423SLionel Sambuc mode_t get_mode(struct inode *ino, int mode)
19433d6423SLionel Sambuc {
20433d6423SLionel Sambuc /* Return the mode for an inode, given the inode and the retrieved mode.
21433d6423SLionel Sambuc  */
22433d6423SLionel Sambuc 
23433d6423SLionel Sambuc   mode &= S_IRWXU;
24433d6423SLionel Sambuc   mode = mode | (mode >> 3) | (mode >> 6);
25433d6423SLionel Sambuc 
26433d6423SLionel Sambuc   if (IS_DIR(ino))
27433d6423SLionel Sambuc 	mode = S_IFDIR | (mode & sffs_params->p_dir_mask);
28433d6423SLionel Sambuc   else
29433d6423SLionel Sambuc 	mode = S_IFREG | (mode & sffs_params->p_file_mask);
30433d6423SLionel Sambuc 
31289b0467SDavid van Moolenbroek   if (read_only)
32433d6423SLionel Sambuc 	mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
33433d6423SLionel Sambuc 
34433d6423SLionel Sambuc   return mode;
35433d6423SLionel Sambuc }
36433d6423SLionel Sambuc 
37433d6423SLionel Sambuc /*===========================================================================*
38433d6423SLionel Sambuc  *				do_stat					     *
39433d6423SLionel Sambuc  *===========================================================================*/
do_stat(ino_t ino_nr,struct stat * st)40*7c48de6cSDavid van Moolenbroek int do_stat(ino_t ino_nr, struct stat *st)
41433d6423SLionel Sambuc {
42433d6423SLionel Sambuc /* Retrieve inode status.
43433d6423SLionel Sambuc  */
44433d6423SLionel Sambuc   struct inode *ino;
45433d6423SLionel Sambuc   struct sffs_attr attr;
46433d6423SLionel Sambuc   char path[PATH_MAX];
47433d6423SLionel Sambuc   int r;
48433d6423SLionel Sambuc 
49433d6423SLionel Sambuc   /* Don't increase the inode refcount: it's already open anyway */
50433d6423SLionel Sambuc   if ((ino = find_inode(ino_nr)) == NULL)
51433d6423SLionel Sambuc 	return EINVAL;
52433d6423SLionel Sambuc 
53433d6423SLionel Sambuc   attr.a_mask = SFFS_ATTR_MODE | SFFS_ATTR_SIZE | SFFS_ATTR_CRTIME |
54433d6423SLionel Sambuc 		SFFS_ATTR_ATIME | SFFS_ATTR_MTIME | SFFS_ATTR_CTIME;
55433d6423SLionel Sambuc 
56433d6423SLionel Sambuc   if ((r = verify_inode(ino, path, &attr)) != OK)
57433d6423SLionel Sambuc 	return r;
58433d6423SLionel Sambuc 
59*7c48de6cSDavid van Moolenbroek   st->st_mode = get_mode(ino, attr.a_mode);
60*7c48de6cSDavid van Moolenbroek   st->st_uid = sffs_params->p_uid;
61*7c48de6cSDavid van Moolenbroek   st->st_gid = sffs_params->p_gid;
62*7c48de6cSDavid van Moolenbroek   st->st_rdev = NO_DEV;
63*7c48de6cSDavid van Moolenbroek   st->st_size = attr.a_size;
64*7c48de6cSDavid van Moolenbroek   st->st_atimespec = attr.a_atime;
65*7c48de6cSDavid van Moolenbroek   st->st_mtimespec = attr.a_mtime;
66*7c48de6cSDavid van Moolenbroek   st->st_ctimespec = attr.a_ctime;
67*7c48de6cSDavid van Moolenbroek   st->st_birthtimespec = attr.a_crtime;
68433d6423SLionel Sambuc 
69*7c48de6cSDavid van Moolenbroek   st->st_blocks = st->st_size / S_BLKSIZE;
70*7c48de6cSDavid van Moolenbroek   if (st->st_size % S_BLKSIZE != 0)
71*7c48de6cSDavid van Moolenbroek 	st->st_blocks += 1;
72433d6423SLionel Sambuc 
73*7c48de6cSDavid van Moolenbroek   st->st_blksize = BLOCK_SIZE;
74433d6423SLionel Sambuc 
75433d6423SLionel Sambuc   /* We could make this more accurate by iterating over directory inodes'
76433d6423SLionel Sambuc    * children, counting how many of those are directories as well.
77433d6423SLionel Sambuc    * It's just not worth it.
78433d6423SLionel Sambuc    */
79*7c48de6cSDavid van Moolenbroek   st->st_nlink = 0;
80*7c48de6cSDavid van Moolenbroek   if (ino->i_parent != NULL) st->st_nlink++;
81433d6423SLionel Sambuc   if (IS_DIR(ino)) {
82*7c48de6cSDavid van Moolenbroek 	st->st_nlink++;
83*7c48de6cSDavid van Moolenbroek 	if (HAS_CHILDREN(ino)) st->st_nlink++;
84433d6423SLionel Sambuc   }
85433d6423SLionel Sambuc 
86a99c939dSDavid van Moolenbroek   return OK;
87433d6423SLionel Sambuc }
88433d6423SLionel Sambuc 
89433d6423SLionel Sambuc /*===========================================================================*
90433d6423SLionel Sambuc  *				do_chmod				     *
91433d6423SLionel Sambuc  *===========================================================================*/
do_chmod(ino_t ino_nr,mode_t * mode)92a99c939dSDavid van Moolenbroek int do_chmod(ino_t ino_nr, mode_t *mode)
93433d6423SLionel Sambuc {
94433d6423SLionel Sambuc /* Change file mode.
95433d6423SLionel Sambuc  */
96433d6423SLionel Sambuc   struct inode *ino;
97433d6423SLionel Sambuc   char path[PATH_MAX];
98433d6423SLionel Sambuc   struct sffs_attr attr;
99433d6423SLionel Sambuc   int r;
100433d6423SLionel Sambuc 
101289b0467SDavid van Moolenbroek   if (read_only)
102433d6423SLionel Sambuc 	return EROFS;
103433d6423SLionel Sambuc 
104a99c939dSDavid van Moolenbroek   if ((ino = find_inode(ino_nr)) == NULL)
105433d6423SLionel Sambuc 	return EINVAL;
106433d6423SLionel Sambuc 
107433d6423SLionel Sambuc   if ((r = verify_inode(ino, path, NULL)) != OK)
108433d6423SLionel Sambuc 	return r;
109433d6423SLionel Sambuc 
110433d6423SLionel Sambuc   /* Set the new file mode. */
111433d6423SLionel Sambuc   attr.a_mask = SFFS_ATTR_MODE;
112a99c939dSDavid van Moolenbroek   attr.a_mode = *mode; /* no need to convert in this direction */
113433d6423SLionel Sambuc 
114433d6423SLionel Sambuc   if ((r = sffs_table->t_setattr(path, &attr)) != OK)
115433d6423SLionel Sambuc 	return r;
116433d6423SLionel Sambuc 
117433d6423SLionel Sambuc   /* We have no idea what really happened. Query for the mode again. */
118433d6423SLionel Sambuc   if ((r = verify_path(path, ino, &attr, NULL)) != OK)
119433d6423SLionel Sambuc 	return r;
120433d6423SLionel Sambuc 
121a99c939dSDavid van Moolenbroek   *mode = get_mode(ino, attr.a_mode);
122433d6423SLionel Sambuc 
123433d6423SLionel Sambuc   return OK;
124433d6423SLionel Sambuc }
125433d6423SLionel Sambuc 
126433d6423SLionel Sambuc /*===========================================================================*
127433d6423SLionel Sambuc  *				do_utime				     *
128433d6423SLionel Sambuc  *===========================================================================*/
do_utime(ino_t ino_nr,struct timespec * atime,struct timespec * mtime)129a99c939dSDavid van Moolenbroek int do_utime(ino_t ino_nr, struct timespec *atime, struct timespec *mtime)
130433d6423SLionel Sambuc {
131433d6423SLionel Sambuc /* Set file times.
132433d6423SLionel Sambuc  */
133433d6423SLionel Sambuc   struct inode *ino;
134433d6423SLionel Sambuc   char path[PATH_MAX];
135433d6423SLionel Sambuc   struct sffs_attr attr;
136433d6423SLionel Sambuc   int r;
137433d6423SLionel Sambuc 
138289b0467SDavid van Moolenbroek   if (read_only)
139433d6423SLionel Sambuc 	return EROFS;
140433d6423SLionel Sambuc 
141a99c939dSDavid van Moolenbroek   if ((ino = find_inode(ino_nr)) == NULL)
142433d6423SLionel Sambuc 	return EINVAL;
143433d6423SLionel Sambuc 
144433d6423SLionel Sambuc   if ((r = verify_inode(ino, path, NULL)) != OK)
145433d6423SLionel Sambuc 	return r;
146433d6423SLionel Sambuc 
147433d6423SLionel Sambuc   attr.a_mask = 0;
148433d6423SLionel Sambuc 
149a99c939dSDavid van Moolenbroek   switch (atime->tv_nsec) {
150433d6423SLionel Sambuc   case UTIME_OMIT: /* do not touch */
151433d6423SLionel Sambuc 	break;
152433d6423SLionel Sambuc   case UTIME_NOW:
153433d6423SLionel Sambuc 	/* XXX VFS should have time() into ACTIME, for compat; we trust it! */
154a99c939dSDavid van Moolenbroek 	atime->tv_nsec = 0;
155433d6423SLionel Sambuc 	/*FALLTHROUGH*/
156433d6423SLionel Sambuc   default:
157a99c939dSDavid van Moolenbroek 	attr.a_atime = *atime;
158433d6423SLionel Sambuc 	attr.a_mask |= SFFS_ATTR_ATIME;
159433d6423SLionel Sambuc 	break;
160433d6423SLionel Sambuc   }
161a99c939dSDavid van Moolenbroek 
162a99c939dSDavid van Moolenbroek   switch (mtime->tv_nsec) {
163433d6423SLionel Sambuc   case UTIME_OMIT: /* do not touch */
164433d6423SLionel Sambuc 	break;
165433d6423SLionel Sambuc   case UTIME_NOW:
166433d6423SLionel Sambuc 	/* XXX VFS should have time() into MODTIME, for compat; we trust it! */
167a99c939dSDavid van Moolenbroek 	mtime->tv_nsec = 0;
168433d6423SLionel Sambuc 	/*FALLTHROUGH*/
169433d6423SLionel Sambuc   default:
170a99c939dSDavid van Moolenbroek 	attr.a_mtime = *mtime;
171433d6423SLionel Sambuc 	attr.a_mask |= SFFS_ATTR_MTIME;
172433d6423SLionel Sambuc 	break;
173433d6423SLionel Sambuc   }
174a99c939dSDavid van Moolenbroek 
175433d6423SLionel Sambuc   return sffs_table->t_setattr(path, &attr);
176433d6423SLionel Sambuc }
177