xref: /minix3/minix/lib/libvboxfs/attr.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc /* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
2*433d6423SLionel Sambuc 
3*433d6423SLionel Sambuc #include "inc.h"
4*433d6423SLionel Sambuc 
5*433d6423SLionel Sambuc /*
6*433d6423SLionel Sambuc  * Convert a VirtualBox timestamp to a POSIX timespec structure.
7*433d6423SLionel Sambuc  * VirtualBox' timestamps are in nanoseconds since the UNIX epoch.
8*433d6423SLionel Sambuc  */
9*433d6423SLionel Sambuc static void
10*433d6423SLionel Sambuc get_time(struct timespec *tsp, u64_t nsecs)
11*433d6423SLionel Sambuc {
12*433d6423SLionel Sambuc 
13*433d6423SLionel Sambuc 	tsp->tv_sec = (unsigned long)(nsecs / 1000000000);
14*433d6423SLionel Sambuc 	tsp->tv_nsec = (unsigned)(nsecs % 1000000000);
15*433d6423SLionel Sambuc }
16*433d6423SLionel Sambuc 
17*433d6423SLionel Sambuc /*
18*433d6423SLionel Sambuc  * Convert a POSIX timespec structure to a VirtualBox timestamp.
19*433d6423SLionel Sambuc  */
20*433d6423SLionel Sambuc static u64_t
21*433d6423SLionel Sambuc set_time(struct timespec *tsp)
22*433d6423SLionel Sambuc {
23*433d6423SLionel Sambuc 
24*433d6423SLionel Sambuc 	return ((u64_t)tsp->tv_sec * 1000000000) + tsp->tv_nsec;
25*433d6423SLionel Sambuc }
26*433d6423SLionel Sambuc 
27*433d6423SLionel Sambuc /*
28*433d6423SLionel Sambuc  * Fill the given attribute structure with VirtualBox object information.
29*433d6423SLionel Sambuc  */
30*433d6423SLionel Sambuc void
31*433d6423SLionel Sambuc vboxfs_get_attr(struct sffs_attr *attr, vboxfs_objinfo_t *info)
32*433d6423SLionel Sambuc {
33*433d6423SLionel Sambuc 
34*433d6423SLionel Sambuc 	if (attr->a_mask & SFFS_ATTR_SIZE)
35*433d6423SLionel Sambuc 		attr->a_size = info->size;
36*433d6423SLionel Sambuc 	if (attr->a_mask & SFFS_ATTR_MODE)
37*433d6423SLionel Sambuc 		attr->a_mode = VBOXFS_GET_MODE(info->attr.mode);
38*433d6423SLionel Sambuc 	if (attr->a_mask & SFFS_ATTR_ATIME)
39*433d6423SLionel Sambuc 		get_time(&attr->a_atime, info->atime);
40*433d6423SLionel Sambuc 	if (attr->a_mask & SFFS_ATTR_MTIME)
41*433d6423SLionel Sambuc 		get_time(&attr->a_mtime, info->mtime);
42*433d6423SLionel Sambuc 	if (attr->a_mask & SFFS_ATTR_CTIME)
43*433d6423SLionel Sambuc 		get_time(&attr->a_ctime, info->ctime);
44*433d6423SLionel Sambuc 	if (attr->a_mask & SFFS_ATTR_CRTIME)
45*433d6423SLionel Sambuc 		get_time(&attr->a_crtime, info->crtime);
46*433d6423SLionel Sambuc }
47*433d6423SLionel Sambuc 
48*433d6423SLionel Sambuc /*
49*433d6423SLionel Sambuc  * Get file attributes.
50*433d6423SLionel Sambuc  */
51*433d6423SLionel Sambuc int
52*433d6423SLionel Sambuc vboxfs_getattr(char *path, struct sffs_attr *attr)
53*433d6423SLionel Sambuc {
54*433d6423SLionel Sambuc 	vbox_param_t param[3];
55*433d6423SLionel Sambuc 	vboxfs_path_t pathbuf;
56*433d6423SLionel Sambuc 	vboxfs_crinfo_t crinfo;
57*433d6423SLionel Sambuc 	int r;
58*433d6423SLionel Sambuc 
59*433d6423SLionel Sambuc 	if ((r = vboxfs_set_path(&pathbuf, path)) != OK)
60*433d6423SLionel Sambuc 		return r;
61*433d6423SLionel Sambuc 
62*433d6423SLionel Sambuc 	memset(&crinfo, 0, sizeof(crinfo));
63*433d6423SLionel Sambuc 	crinfo.flags = VBOXFS_CRFLAG_LOOKUP;
64*433d6423SLionel Sambuc 	/* crinfo.info.attr.add is not checked */
65*433d6423SLionel Sambuc 
66*433d6423SLionel Sambuc 	vbox_set_u32(&param[0], vboxfs_root);
67*433d6423SLionel Sambuc 	vbox_set_ptr(&param[1], &pathbuf, vboxfs_get_path_size(&pathbuf),
68*433d6423SLionel Sambuc 	    VBOX_DIR_OUT);
69*433d6423SLionel Sambuc 	vbox_set_ptr(&param[2], &crinfo, sizeof(crinfo), VBOX_DIR_INOUT);
70*433d6423SLionel Sambuc 
71*433d6423SLionel Sambuc 	r = vbox_call(vboxfs_conn, VBOXFS_CALL_CREATE, param, 3, NULL);
72*433d6423SLionel Sambuc 	if (r != OK)
73*433d6423SLionel Sambuc 		return r;
74*433d6423SLionel Sambuc 
75*433d6423SLionel Sambuc 	switch (crinfo.result) {
76*433d6423SLionel Sambuc 	case VBOXFS_PATH_NOT_FOUND:
77*433d6423SLionel Sambuc 		/* This could also be ENOTDIR. See note in handle.c. */
78*433d6423SLionel Sambuc 	case VBOXFS_FILE_NOT_FOUND:
79*433d6423SLionel Sambuc 		return ENOENT;
80*433d6423SLionel Sambuc 	case VBOXFS_FILE_EXISTS:
81*433d6423SLionel Sambuc 		break;			/* success */
82*433d6423SLionel Sambuc 	default:
83*433d6423SLionel Sambuc 		return EIO;		/* should never happen */
84*433d6423SLionel Sambuc 	}
85*433d6423SLionel Sambuc 
86*433d6423SLionel Sambuc 	vboxfs_get_attr(attr, &crinfo.info);
87*433d6423SLionel Sambuc 
88*433d6423SLionel Sambuc 	return OK;
89*433d6423SLionel Sambuc }
90*433d6423SLionel Sambuc 
91*433d6423SLionel Sambuc /*
92*433d6423SLionel Sambuc  * Set file size.
93*433d6423SLionel Sambuc  */
94*433d6423SLionel Sambuc static int
95*433d6423SLionel Sambuc set_size(char *path, u64_t size)
96*433d6423SLionel Sambuc {
97*433d6423SLionel Sambuc 	vboxfs_objinfo_t info;
98*433d6423SLionel Sambuc 	vboxfs_handle_t h;
99*433d6423SLionel Sambuc 	int r;
100*433d6423SLionel Sambuc 
101*433d6423SLionel Sambuc 	if ((r = vboxfs_open_file(path, O_WRONLY, S_IFREG, &h, NULL)) != OK)
102*433d6423SLionel Sambuc 		return r;
103*433d6423SLionel Sambuc 
104*433d6423SLionel Sambuc 	memset(&info, 0, sizeof(info));
105*433d6423SLionel Sambuc 	info.size = size;
106*433d6423SLionel Sambuc 
107*433d6423SLionel Sambuc 	r = vboxfs_getset_info(h, VBOXFS_INFO_SET | VBOXFS_INFO_SIZE, &info,
108*433d6423SLionel Sambuc 	    sizeof(info));
109*433d6423SLionel Sambuc 
110*433d6423SLionel Sambuc 	vboxfs_close_file(h);
111*433d6423SLionel Sambuc 
112*433d6423SLionel Sambuc 	return r;
113*433d6423SLionel Sambuc }
114*433d6423SLionel Sambuc 
115*433d6423SLionel Sambuc /*
116*433d6423SLionel Sambuc  * Set file attributes.
117*433d6423SLionel Sambuc  */
118*433d6423SLionel Sambuc int
119*433d6423SLionel Sambuc vboxfs_setattr(char *path, struct sffs_attr *attr)
120*433d6423SLionel Sambuc {
121*433d6423SLionel Sambuc 	vboxfs_objinfo_t info;
122*433d6423SLionel Sambuc 	vboxfs_handle_t h;
123*433d6423SLionel Sambuc 	int r;
124*433d6423SLionel Sambuc 
125*433d6423SLionel Sambuc 	/*
126*433d6423SLionel Sambuc 	 * Setting the size of a path cannot be combined with other attribute
127*433d6423SLionel Sambuc 	 * modifications, because we cannot fail atomically.
128*433d6423SLionel Sambuc 	 */
129*433d6423SLionel Sambuc 	if (attr->a_mask & SFFS_ATTR_SIZE) {
130*433d6423SLionel Sambuc 		assert(attr->a_mask == SFFS_ATTR_SIZE);
131*433d6423SLionel Sambuc 
132*433d6423SLionel Sambuc 		return set_size(path, attr->a_size);
133*433d6423SLionel Sambuc 	}
134*433d6423SLionel Sambuc 
135*433d6423SLionel Sambuc 	/*
136*433d6423SLionel Sambuc 	 * By passing a pointer to an object information structure, we open the
137*433d6423SLionel Sambuc 	 * file for attribute manipulation.  Note that this call will open the
138*433d6423SLionel Sambuc 	 * file as a regular file.  This works on directories as well.
139*433d6423SLionel Sambuc 	 */
140*433d6423SLionel Sambuc 	if ((r = vboxfs_open_file(path, O_WRONLY, 0, &h, &info)) != OK)
141*433d6423SLionel Sambuc 		return r;
142*433d6423SLionel Sambuc 
143*433d6423SLionel Sambuc 	info.attr.add = VBOXFS_OBJATTR_ADD_NONE;
144*433d6423SLionel Sambuc 
145*433d6423SLionel Sambuc 	/* Update the file's permissions if requested. */
146*433d6423SLionel Sambuc 	if (attr->a_mask & SFFS_ATTR_MODE)
147*433d6423SLionel Sambuc 		info.attr.mode =
148*433d6423SLionel Sambuc 		    VBOXFS_SET_MODE(info.attr.mode & S_IFMT, attr->a_mode);
149*433d6423SLionel Sambuc 
150*433d6423SLionel Sambuc 	/*
151*433d6423SLionel Sambuc 	 * Update various file times if requested.  Not all changes may
152*433d6423SLionel Sambuc 	 * be honered.  A zero time indicates no change.
153*433d6423SLionel Sambuc 	 */
154*433d6423SLionel Sambuc 	info.atime = (attr->a_mask & SFFS_ATTR_ATIME) ?
155*433d6423SLionel Sambuc 	    set_time(&attr->a_atime) : 0;
156*433d6423SLionel Sambuc 	info.mtime = (attr->a_mask & SFFS_ATTR_MTIME) ?
157*433d6423SLionel Sambuc 	    set_time(&attr->a_mtime) : 0;
158*433d6423SLionel Sambuc 	info.ctime = (attr->a_mask & SFFS_ATTR_CTIME) ?
159*433d6423SLionel Sambuc 	    set_time(&attr->a_ctime) : 0;
160*433d6423SLionel Sambuc 	info.crtime = (attr->a_mask & SFFS_ATTR_CRTIME) ?
161*433d6423SLionel Sambuc 	    set_time(&attr->a_crtime) : 0;
162*433d6423SLionel Sambuc 
163*433d6423SLionel Sambuc 	r = vboxfs_getset_info(h, VBOXFS_INFO_SET | VBOXFS_INFO_FILE, &info,
164*433d6423SLionel Sambuc 	    sizeof(info));
165*433d6423SLionel Sambuc 
166*433d6423SLionel Sambuc 	vboxfs_close_file(h);
167*433d6423SLionel Sambuc 
168*433d6423SLionel Sambuc 	return r;
169*433d6423SLionel Sambuc }
170