add opendir alias
[minix.git] / lib / libvboxfs / attr.c
blob6017748a84eda3d369993192e467f433044c790c
1 /* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
3 #include "inc.h"
5 /*
6 * Convert a VirtualBox timestamp to a POSIX timespec structure.
7 * VirtualBox' timestamps are in nanoseconds since the UNIX epoch.
8 */
9 static void
10 get_time(struct timespec *tsp, u64_t nsecs)
13 tsp->tv_sec = div64u(nsecs, 1000000000);
14 tsp->tv_nsec = rem64u(nsecs, 1000000000);
18 * Convert a POSIX timespec structure to a VirtualBox timestamp.
20 static u64_t
21 set_time(struct timespec *tsp)
24 return add64u(mul64u(tsp->tv_sec, 1000000000), tsp->tv_nsec);
28 * Fill the given attribute structure with VirtualBox object information.
30 void
31 vboxfs_get_attr(struct sffs_attr *attr, vboxfs_objinfo_t *info)
34 if (attr->a_mask & SFFS_ATTR_SIZE)
35 attr->a_size = info->size;
36 if (attr->a_mask & SFFS_ATTR_MODE)
37 attr->a_mode = VBOXFS_GET_MODE(info->attr.mode);
38 if (attr->a_mask & SFFS_ATTR_ATIME)
39 get_time(&attr->a_atime, info->atime);
40 if (attr->a_mask & SFFS_ATTR_MTIME)
41 get_time(&attr->a_mtime, info->mtime);
42 if (attr->a_mask & SFFS_ATTR_CTIME)
43 get_time(&attr->a_ctime, info->ctime);
44 if (attr->a_mask & SFFS_ATTR_CRTIME)
45 get_time(&attr->a_crtime, info->crtime);
49 * Get file attributes.
51 int
52 vboxfs_getattr(char *path, struct sffs_attr *attr)
54 vbox_param_t param[3];
55 vboxfs_path_t pathbuf;
56 vboxfs_crinfo_t crinfo;
57 int r;
59 if ((r = vboxfs_set_path(&pathbuf, path)) != OK)
60 return r;
62 memset(&crinfo, 0, sizeof(crinfo));
63 crinfo.flags = VBOXFS_CRFLAG_LOOKUP;
64 /* crinfo.info.attr.add is not checked */
66 vbox_set_u32(&param[0], vboxfs_root);
67 vbox_set_ptr(&param[1], &pathbuf, vboxfs_get_path_size(&pathbuf),
68 VBOX_DIR_OUT);
69 vbox_set_ptr(&param[2], &crinfo, sizeof(crinfo), VBOX_DIR_INOUT);
71 r = vbox_call(vboxfs_conn, VBOXFS_CALL_CREATE, param, 3, NULL);
72 if (r != OK)
73 return r;
75 switch (crinfo.result) {
76 case VBOXFS_PATH_NOT_FOUND:
77 /* This could also be ENOTDIR. See note in handle.c. */
78 case VBOXFS_FILE_NOT_FOUND:
79 return ENOENT;
80 case VBOXFS_FILE_EXISTS:
81 break; /* success */
82 default:
83 return EIO; /* should never happen */
86 vboxfs_get_attr(attr, &crinfo.info);
88 return OK;
92 * Set file size.
94 static int
95 set_size(char *path, u64_t size)
97 vboxfs_objinfo_t info;
98 vboxfs_handle_t h;
99 int r;
101 if ((r = vboxfs_open_file(path, O_WRONLY, S_IFREG, &h, NULL)) != OK)
102 return r;
104 memset(&info, 0, sizeof(info));
105 info.size = size;
107 r = vboxfs_getset_info(h, VBOXFS_INFO_SET | VBOXFS_INFO_SIZE, &info,
108 sizeof(info));
110 vboxfs_close_file(h);
112 return r;
116 * Set file attributes.
119 vboxfs_setattr(char *path, struct sffs_attr *attr)
121 vboxfs_objinfo_t info;
122 vboxfs_handle_t h;
123 int r;
126 * Setting the size of a path cannot be combined with other attribute
127 * modifications, because we cannot fail atomically.
129 if (attr->a_mask & SFFS_ATTR_SIZE) {
130 assert(attr->a_mask == SFFS_ATTR_SIZE);
132 return set_size(path, attr->a_size);
136 * By passing a pointer to an object information structure, we open the
137 * file for attribute manipulation. Note that this call will open the
138 * file as a regular file. This works on directories as well.
140 if ((r = vboxfs_open_file(path, O_WRONLY, 0, &h, &info)) != OK)
141 return r;
143 info.attr.add = VBOXFS_OBJATTR_ADD_NONE;
145 /* Update the file's permissions if requested. */
146 if (attr->a_mask & SFFS_ATTR_MODE)
147 info.attr.mode =
148 VBOXFS_SET_MODE(info.attr.mode & S_IFMT, attr->a_mode);
151 * Update various file times if requested. Not all changes may
152 * be honered. A zero time indicates no change.
154 info.atime = (attr->a_mask & SFFS_ATTR_ATIME) ?
155 set_time(&attr->a_atime) : 0;
156 info.mtime = (attr->a_mask & SFFS_ATTR_MTIME) ?
157 set_time(&attr->a_mtime) : 0;
158 info.ctime = (attr->a_mask & SFFS_ATTR_CTIME) ?
159 set_time(&attr->a_ctime) : 0;
160 info.crtime = (attr->a_mask & SFFS_ATTR_CRTIME) ?
161 set_time(&attr->a_crtime) : 0;
163 r = vboxfs_getset_info(h, VBOXFS_INFO_SET | VBOXFS_INFO_FILE, &info,
164 sizeof(info));
166 vboxfs_close_file(h);
168 return r;