/* 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(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(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(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; }