xref: /minix/minix/lib/libvboxfs/attr.c (revision 7f5f010b)
1 /* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
2 
3 #include "inc.h"
4 
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)
11 {
12 
13 	tsp->tv_sec = (unsigned long)(nsecs / 1000000000);
14 	tsp->tv_nsec = (unsigned)(nsecs % 1000000000);
15 }
16 
17 /*
18  * Convert a POSIX timespec structure to a VirtualBox timestamp.
19  */
20 static u64_t
21 set_time(struct timespec *tsp)
22 {
23 
24 	return ((u64_t)tsp->tv_sec * 1000000000) + tsp->tv_nsec;
25 }
26 
27 /*
28  * Fill the given attribute structure with VirtualBox object information.
29  */
30 void
31 vboxfs_get_attr(struct sffs_attr *attr, vboxfs_objinfo_t *info)
32 {
33 
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);
46 }
47 
48 /*
49  * Get file attributes.
50  */
51 int
52 vboxfs_getattr(char *path, struct sffs_attr *attr)
53 {
54 	vbox_param_t param[3];
55 	vboxfs_path_t pathbuf;
56 	vboxfs_crinfo_t crinfo;
57 	int r;
58 
59 	if ((r = vboxfs_set_path(&pathbuf, path)) != OK)
60 		return r;
61 
62 	memset(&crinfo, 0, sizeof(crinfo));
63 	crinfo.flags = VBOXFS_CRFLAG_LOOKUP;
64 	/* crinfo.info.attr.add is not checked */
65 
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);
70 
71 	r = vbox_call(vboxfs_conn, VBOXFS_CALL_CREATE, param, 3, NULL);
72 	if (r != OK)
73 		return r;
74 
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 */
84 	}
85 
86 	vboxfs_get_attr(attr, &crinfo.info);
87 
88 	return OK;
89 }
90 
91 /*
92  * Set file size.
93  */
94 static int
95 set_size(char *path, u64_t size)
96 {
97 	vboxfs_objinfo_t info;
98 	vboxfs_handle_t h;
99 	int r;
100 
101 	if ((r = vboxfs_open_file(path, O_WRONLY, S_IFREG, &h, NULL)) != OK)
102 		return r;
103 
104 	memset(&info, 0, sizeof(info));
105 	info.size = size;
106 
107 	r = vboxfs_getset_info(h, VBOXFS_INFO_SET | VBOXFS_INFO_SIZE, &info,
108 	    sizeof(info));
109 
110 	vboxfs_close_file(h);
111 
112 	return r;
113 }
114 
115 /*
116  * Set file attributes.
117  */
118 int
119 vboxfs_setattr(char *path, struct sffs_attr *attr)
120 {
121 	vboxfs_objinfo_t info;
122 	vboxfs_handle_t h;
123 	int r;
124 
125 	/*
126 	 * Setting the size of a path cannot be combined with other attribute
127 	 * modifications, because we cannot fail atomically.
128 	 */
129 	if (attr->a_mask & SFFS_ATTR_SIZE) {
130 		assert(attr->a_mask == SFFS_ATTR_SIZE);
131 
132 		return set_size(path, attr->a_size);
133 	}
134 
135 	/*
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.
139 	 */
140 	if ((r = vboxfs_open_file(path, O_WRONLY, 0, &h, &info)) != OK)
141 		return r;
142 
143 	info.attr.add = VBOXFS_OBJATTR_ADD_NONE;
144 
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);
149 
150 	/*
151 	 * Update various file times if requested.  Not all changes may
152 	 * be honered.  A zero time indicates no change.
153 	 */
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;
162 
163 	r = vboxfs_getset_info(h, VBOXFS_INFO_SET | VBOXFS_INFO_FILE, &info,
164 	    sizeof(info));
165 
166 	vboxfs_close_file(h);
167 
168 	return r;
169 }
170