1433d6423SLionel Sambuc /* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
2433d6423SLionel Sambuc
3433d6423SLionel Sambuc #include "inc.h"
4433d6423SLionel Sambuc
5433d6423SLionel Sambuc /*
6433d6423SLionel Sambuc * Convert a VirtualBox timestamp to a POSIX timespec structure.
7433d6423SLionel Sambuc * VirtualBox' timestamps are in nanoseconds since the UNIX epoch.
8433d6423SLionel Sambuc */
9433d6423SLionel Sambuc static void
get_time(struct timespec * tsp,u64_t nsecs)10433d6423SLionel Sambuc get_time(struct timespec *tsp, u64_t nsecs)
11433d6423SLionel Sambuc {
12433d6423SLionel Sambuc
13433d6423SLionel Sambuc tsp->tv_sec = (unsigned long)(nsecs / 1000000000);
14433d6423SLionel Sambuc tsp->tv_nsec = (unsigned)(nsecs % 1000000000);
15433d6423SLionel Sambuc }
16433d6423SLionel Sambuc
17433d6423SLionel Sambuc /*
18433d6423SLionel Sambuc * Convert a POSIX timespec structure to a VirtualBox timestamp.
19433d6423SLionel Sambuc */
20433d6423SLionel Sambuc static u64_t
set_time(struct timespec * tsp)21433d6423SLionel Sambuc set_time(struct timespec *tsp)
22433d6423SLionel Sambuc {
23433d6423SLionel Sambuc
24433d6423SLionel Sambuc return ((u64_t)tsp->tv_sec * 1000000000) + tsp->tv_nsec;
25433d6423SLionel Sambuc }
26433d6423SLionel Sambuc
27433d6423SLionel Sambuc /*
28433d6423SLionel Sambuc * Fill the given attribute structure with VirtualBox object information.
29433d6423SLionel Sambuc */
30433d6423SLionel Sambuc void
vboxfs_get_attr(struct sffs_attr * attr,vboxfs_objinfo_t * info)31433d6423SLionel Sambuc vboxfs_get_attr(struct sffs_attr *attr, vboxfs_objinfo_t *info)
32433d6423SLionel Sambuc {
33433d6423SLionel Sambuc
34433d6423SLionel Sambuc if (attr->a_mask & SFFS_ATTR_SIZE)
35433d6423SLionel Sambuc attr->a_size = info->size;
36433d6423SLionel Sambuc if (attr->a_mask & SFFS_ATTR_MODE)
37433d6423SLionel Sambuc attr->a_mode = VBOXFS_GET_MODE(info->attr.mode);
38433d6423SLionel Sambuc if (attr->a_mask & SFFS_ATTR_ATIME)
39433d6423SLionel Sambuc get_time(&attr->a_atime, info->atime);
40433d6423SLionel Sambuc if (attr->a_mask & SFFS_ATTR_MTIME)
41433d6423SLionel Sambuc get_time(&attr->a_mtime, info->mtime);
42433d6423SLionel Sambuc if (attr->a_mask & SFFS_ATTR_CTIME)
43433d6423SLionel Sambuc get_time(&attr->a_ctime, info->ctime);
44433d6423SLionel Sambuc if (attr->a_mask & SFFS_ATTR_CRTIME)
45433d6423SLionel Sambuc get_time(&attr->a_crtime, info->crtime);
46433d6423SLionel Sambuc }
47433d6423SLionel Sambuc
48433d6423SLionel Sambuc /*
49433d6423SLionel Sambuc * Get file attributes.
50433d6423SLionel Sambuc */
51433d6423SLionel Sambuc int
vboxfs_getattr(const char * path,struct sffs_attr * attr)52*94e65446SDavid van Moolenbroek vboxfs_getattr(const char *path, struct sffs_attr *attr)
53433d6423SLionel Sambuc {
54433d6423SLionel Sambuc vbox_param_t param[3];
55433d6423SLionel Sambuc vboxfs_path_t pathbuf;
56433d6423SLionel Sambuc vboxfs_crinfo_t crinfo;
57433d6423SLionel Sambuc int r;
58433d6423SLionel Sambuc
59433d6423SLionel Sambuc if ((r = vboxfs_set_path(&pathbuf, path)) != OK)
60433d6423SLionel Sambuc return r;
61433d6423SLionel Sambuc
62433d6423SLionel Sambuc memset(&crinfo, 0, sizeof(crinfo));
63433d6423SLionel Sambuc crinfo.flags = VBOXFS_CRFLAG_LOOKUP;
64433d6423SLionel Sambuc /* crinfo.info.attr.add is not checked */
65433d6423SLionel Sambuc
66433d6423SLionel Sambuc vbox_set_u32(¶m[0], vboxfs_root);
67433d6423SLionel Sambuc vbox_set_ptr(¶m[1], &pathbuf, vboxfs_get_path_size(&pathbuf),
68433d6423SLionel Sambuc VBOX_DIR_OUT);
69433d6423SLionel Sambuc vbox_set_ptr(¶m[2], &crinfo, sizeof(crinfo), VBOX_DIR_INOUT);
70433d6423SLionel Sambuc
71433d6423SLionel Sambuc r = vbox_call(vboxfs_conn, VBOXFS_CALL_CREATE, param, 3, NULL);
72433d6423SLionel Sambuc if (r != OK)
73433d6423SLionel Sambuc return r;
74433d6423SLionel Sambuc
75433d6423SLionel Sambuc switch (crinfo.result) {
76433d6423SLionel Sambuc case VBOXFS_PATH_NOT_FOUND:
77433d6423SLionel Sambuc /* This could also be ENOTDIR. See note in handle.c. */
78433d6423SLionel Sambuc case VBOXFS_FILE_NOT_FOUND:
79433d6423SLionel Sambuc return ENOENT;
80433d6423SLionel Sambuc case VBOXFS_FILE_EXISTS:
81433d6423SLionel Sambuc break; /* success */
82433d6423SLionel Sambuc default:
83433d6423SLionel Sambuc return EIO; /* should never happen */
84433d6423SLionel Sambuc }
85433d6423SLionel Sambuc
86433d6423SLionel Sambuc vboxfs_get_attr(attr, &crinfo.info);
87433d6423SLionel Sambuc
88433d6423SLionel Sambuc return OK;
89433d6423SLionel Sambuc }
90433d6423SLionel Sambuc
91433d6423SLionel Sambuc /*
92433d6423SLionel Sambuc * Set file size.
93433d6423SLionel Sambuc */
94433d6423SLionel Sambuc static int
set_size(const char * path,u64_t size)95*94e65446SDavid van Moolenbroek set_size(const char *path, u64_t size)
96433d6423SLionel Sambuc {
97433d6423SLionel Sambuc vboxfs_objinfo_t info;
98433d6423SLionel Sambuc vboxfs_handle_t h;
99433d6423SLionel Sambuc int r;
100433d6423SLionel Sambuc
101433d6423SLionel Sambuc if ((r = vboxfs_open_file(path, O_WRONLY, S_IFREG, &h, NULL)) != OK)
102433d6423SLionel Sambuc return r;
103433d6423SLionel Sambuc
104433d6423SLionel Sambuc memset(&info, 0, sizeof(info));
105433d6423SLionel Sambuc info.size = size;
106433d6423SLionel Sambuc
107433d6423SLionel Sambuc r = vboxfs_getset_info(h, VBOXFS_INFO_SET | VBOXFS_INFO_SIZE, &info,
108433d6423SLionel Sambuc sizeof(info));
109433d6423SLionel Sambuc
110433d6423SLionel Sambuc vboxfs_close_file(h);
111433d6423SLionel Sambuc
112433d6423SLionel Sambuc return r;
113433d6423SLionel Sambuc }
114433d6423SLionel Sambuc
115433d6423SLionel Sambuc /*
116433d6423SLionel Sambuc * Set file attributes.
117433d6423SLionel Sambuc */
118433d6423SLionel Sambuc int
vboxfs_setattr(const char * path,struct sffs_attr * attr)119*94e65446SDavid van Moolenbroek vboxfs_setattr(const char *path, struct sffs_attr *attr)
120433d6423SLionel Sambuc {
121433d6423SLionel Sambuc vboxfs_objinfo_t info;
122433d6423SLionel Sambuc vboxfs_handle_t h;
123433d6423SLionel Sambuc int r;
124433d6423SLionel Sambuc
125433d6423SLionel Sambuc /*
126433d6423SLionel Sambuc * Setting the size of a path cannot be combined with other attribute
127433d6423SLionel Sambuc * modifications, because we cannot fail atomically.
128433d6423SLionel Sambuc */
129433d6423SLionel Sambuc if (attr->a_mask & SFFS_ATTR_SIZE) {
130433d6423SLionel Sambuc assert(attr->a_mask == SFFS_ATTR_SIZE);
131433d6423SLionel Sambuc
132433d6423SLionel Sambuc return set_size(path, attr->a_size);
133433d6423SLionel Sambuc }
134433d6423SLionel Sambuc
135433d6423SLionel Sambuc /*
136433d6423SLionel Sambuc * By passing a pointer to an object information structure, we open the
137433d6423SLionel Sambuc * file for attribute manipulation. Note that this call will open the
138433d6423SLionel Sambuc * file as a regular file. This works on directories as well.
139433d6423SLionel Sambuc */
140433d6423SLionel Sambuc if ((r = vboxfs_open_file(path, O_WRONLY, 0, &h, &info)) != OK)
141433d6423SLionel Sambuc return r;
142433d6423SLionel Sambuc
143433d6423SLionel Sambuc info.attr.add = VBOXFS_OBJATTR_ADD_NONE;
144433d6423SLionel Sambuc
145433d6423SLionel Sambuc /* Update the file's permissions if requested. */
146433d6423SLionel Sambuc if (attr->a_mask & SFFS_ATTR_MODE)
147433d6423SLionel Sambuc info.attr.mode =
148433d6423SLionel Sambuc VBOXFS_SET_MODE(info.attr.mode & S_IFMT, attr->a_mode);
149433d6423SLionel Sambuc
150433d6423SLionel Sambuc /*
151433d6423SLionel Sambuc * Update various file times if requested. Not all changes may
152433d6423SLionel Sambuc * be honered. A zero time indicates no change.
153433d6423SLionel Sambuc */
154433d6423SLionel Sambuc info.atime = (attr->a_mask & SFFS_ATTR_ATIME) ?
155433d6423SLionel Sambuc set_time(&attr->a_atime) : 0;
156433d6423SLionel Sambuc info.mtime = (attr->a_mask & SFFS_ATTR_MTIME) ?
157433d6423SLionel Sambuc set_time(&attr->a_mtime) : 0;
158433d6423SLionel Sambuc info.ctime = (attr->a_mask & SFFS_ATTR_CTIME) ?
159433d6423SLionel Sambuc set_time(&attr->a_ctime) : 0;
160433d6423SLionel Sambuc info.crtime = (attr->a_mask & SFFS_ATTR_CRTIME) ?
161433d6423SLionel Sambuc set_time(&attr->a_crtime) : 0;
162433d6423SLionel Sambuc
163433d6423SLionel Sambuc r = vboxfs_getset_info(h, VBOXFS_INFO_SET | VBOXFS_INFO_FILE, &info,
164433d6423SLionel Sambuc sizeof(info));
165433d6423SLionel Sambuc
166433d6423SLionel Sambuc vboxfs_close_file(h);
167433d6423SLionel Sambuc
168433d6423SLionel Sambuc return r;
169433d6423SLionel Sambuc }
170