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