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