mkfs, mkproto: minor improvements
[minix.git] / lib / libsffs / stat.c
blobdbac8086743306b434881f88ea3d75098b5b13c6
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
9 * Created:
10 * April 2009 (D.C. van Moolenbroek)
13 #include "inc.h"
15 /*===========================================================================*
16 * get_mode *
17 *===========================================================================*/
18 mode_t get_mode(ino, mode)
19 struct inode *ino;
20 int mode;
22 /* Return the mode for an inode, given the inode and the retrieved mode.
25 mode &= S_IRWXU;
26 mode = mode | (mode >> 3) | (mode >> 6);
28 if (IS_DIR(ino))
29 mode = S_IFDIR | (mode & sffs_params->p_dir_mask);
30 else
31 mode = S_IFREG | (mode & sffs_params->p_file_mask);
33 if (state.s_read_only)
34 mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
36 return mode;
39 /*===========================================================================*
40 * do_stat *
41 *===========================================================================*/
42 int do_stat()
44 /* Retrieve inode status.
46 struct inode *ino;
47 struct sffs_attr attr;
48 struct stat stat;
49 char path[PATH_MAX];
50 ino_t ino_nr;
51 int r;
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)
57 return EINVAL;
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)
63 return r;
65 memset(&stat, 0, sizeof(struct stat));
67 stat.st_dev = state.s_dev;
68 stat.st_ino = ino_nr;
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;
75 else
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)
84 stat.st_blocks += 1;
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.
92 stat.st_nlink = 0;
93 if (ino->i_parent != NULL) stat.st_nlink++;
94 if (IS_DIR(ino)) {
95 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 /*===========================================================================*
104 * do_chmod *
105 *===========================================================================*/
106 int do_chmod()
108 /* Change file mode.
110 struct inode *ino;
111 char path[PATH_MAX];
112 struct sffs_attr attr;
113 int r;
115 if (state.s_read_only)
116 return EROFS;
118 if ((ino = find_inode(m_in.REQ_INODE_NR)) == NULL)
119 return EINVAL;
121 if ((r = verify_inode(ino, path, NULL)) != OK)
122 return r;
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)
129 return r;
131 /* We have no idea what really happened. Query for the mode again. */
132 if ((r = verify_path(path, ino, &attr, NULL)) != OK)
133 return r;
135 m_out.RES_MODE = get_mode(ino, attr.a_mode);
137 return OK;
140 /*===========================================================================*
141 * do_utime *
142 *===========================================================================*/
143 int do_utime()
145 /* Set file times.
147 struct inode *ino;
148 char path[PATH_MAX];
149 struct sffs_attr attr;
150 int r;
152 if (state.s_read_only)
153 return EROFS;
155 if ((ino = find_inode(m_in.REQ_INODE_NR)) == NULL)
156 return EINVAL;
158 if ((r = verify_inode(ino, path, NULL)) != OK)
159 return r;
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);