etc/services - sync with NetBSD-8
[minix.git] / minix / lib / libsffs / stat.c
blobb56d075858449558363670fa2d57eb0ff8821c65
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(struct inode *ino, int mode)
20 /* Return the mode for an inode, given the inode and the retrieved mode.
23 mode &= S_IRWXU;
24 mode = mode | (mode >> 3) | (mode >> 6);
26 if (IS_DIR(ino))
27 mode = S_IFDIR | (mode & sffs_params->p_dir_mask);
28 else
29 mode = S_IFREG | (mode & sffs_params->p_file_mask);
31 if (read_only)
32 mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
34 return mode;
37 /*===========================================================================*
38 * do_stat *
39 *===========================================================================*/
40 int do_stat(ino_t ino_nr, struct stat *st)
42 /* Retrieve inode status.
44 struct inode *ino;
45 struct sffs_attr attr;
46 char path[PATH_MAX];
47 int r;
49 /* Don't increase the inode refcount: it's already open anyway */
50 if ((ino = find_inode(ino_nr)) == NULL)
51 return EINVAL;
53 attr.a_mask = SFFS_ATTR_MODE | SFFS_ATTR_SIZE | SFFS_ATTR_CRTIME |
54 SFFS_ATTR_ATIME | SFFS_ATTR_MTIME | SFFS_ATTR_CTIME;
56 if ((r = verify_inode(ino, path, &attr)) != OK)
57 return r;
59 st->st_mode = get_mode(ino, attr.a_mode);
60 st->st_uid = sffs_params->p_uid;
61 st->st_gid = sffs_params->p_gid;
62 st->st_rdev = NO_DEV;
63 st->st_size = attr.a_size;
64 st->st_atimespec = attr.a_atime;
65 st->st_mtimespec = attr.a_mtime;
66 st->st_ctimespec = attr.a_ctime;
67 st->st_birthtimespec = attr.a_crtime;
69 st->st_blocks = st->st_size / S_BLKSIZE;
70 if (st->st_size % S_BLKSIZE != 0)
71 st->st_blocks += 1;
73 st->st_blksize = BLOCK_SIZE;
75 /* We could make this more accurate by iterating over directory inodes'
76 * children, counting how many of those are directories as well.
77 * It's just not worth it.
79 st->st_nlink = 0;
80 if (ino->i_parent != NULL) st->st_nlink++;
81 if (IS_DIR(ino)) {
82 st->st_nlink++;
83 if (HAS_CHILDREN(ino)) st->st_nlink++;
86 return OK;
89 /*===========================================================================*
90 * do_chmod *
91 *===========================================================================*/
92 int do_chmod(ino_t ino_nr, mode_t *mode)
94 /* Change file mode.
96 struct inode *ino;
97 char path[PATH_MAX];
98 struct sffs_attr attr;
99 int r;
101 if (read_only)
102 return EROFS;
104 if ((ino = find_inode(ino_nr)) == NULL)
105 return EINVAL;
107 if ((r = verify_inode(ino, path, NULL)) != OK)
108 return r;
110 /* Set the new file mode. */
111 attr.a_mask = SFFS_ATTR_MODE;
112 attr.a_mode = *mode; /* no need to convert in this direction */
114 if ((r = sffs_table->t_setattr(path, &attr)) != OK)
115 return r;
117 /* We have no idea what really happened. Query for the mode again. */
118 if ((r = verify_path(path, ino, &attr, NULL)) != OK)
119 return r;
121 *mode = get_mode(ino, attr.a_mode);
123 return OK;
126 /*===========================================================================*
127 * do_utime *
128 *===========================================================================*/
129 int do_utime(ino_t ino_nr, struct timespec *atime, struct timespec *mtime)
131 /* Set file times.
133 struct inode *ino;
134 char path[PATH_MAX];
135 struct sffs_attr attr;
136 int r;
138 if (read_only)
139 return EROFS;
141 if ((ino = find_inode(ino_nr)) == NULL)
142 return EINVAL;
144 if ((r = verify_inode(ino, path, NULL)) != OK)
145 return r;
147 attr.a_mask = 0;
149 switch (atime->tv_nsec) {
150 case UTIME_OMIT: /* do not touch */
151 break;
152 case UTIME_NOW:
153 /* XXX VFS should have time() into ACTIME, for compat; we trust it! */
154 atime->tv_nsec = 0;
155 /*FALLTHROUGH*/
156 default:
157 attr.a_atime = *atime;
158 attr.a_mask |= SFFS_ATTR_ATIME;
159 break;
162 switch (mtime->tv_nsec) {
163 case UTIME_OMIT: /* do not touch */
164 break;
165 case UTIME_NOW:
166 /* XXX VFS should have time() into MODTIME, for compat; we trust it! */
167 mtime->tv_nsec = 0;
168 /*FALLTHROUGH*/
169 default:
170 attr.a_mtime = *mtime;
171 attr.a_mask |= SFFS_ATTR_MTIME;
172 break;
175 return sffs_table->t_setattr(path, &attr);