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(const 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(¶m[0], vboxfs_root); 67 vbox_set_ptr(¶m[1], &pathbuf, vboxfs_get_path_size(&pathbuf), 68 VBOX_DIR_OUT); 69 vbox_set_ptr(¶m[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(const 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(const 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