diff options
-rw-r--r-- | int21dos.h | 5 | ||||
-rw-r--r-- | sftsr.c | 84 | ||||
-rw-r--r-- | vboxdev.h | 19 | ||||
-rw-r--r-- | vboxshfl.h | 37 |
4 files changed, 145 insertions, 0 deletions
@@ -195,6 +195,11 @@ typedef _Packed struct dos_search_data_block { } DOSSDB; STATIC_ASSERT(sizeof(DOSSDB) == 21); +typedef _Packed struct dos_lock_params { + uint32_t start_offset; + uint32_t region_size; +} DOSLOCK; + typedef _Packed struct dos_direntry { char filename[11]; uint8_t attr; @@ -58,6 +58,14 @@ static void map_shfl_info_to_dosdir(DOSDIR __far *dir, SHFLFSOBJINFO *i) dir->start_cluster = 0; } +static void map_shfl_info_to_getattr(union INTPACK __far *r, SHFLFSOBJINFO *i) +{ + r->x.ax = map_shfl_attr_to_dosattr(&i->Attr); + r->x.bx = ((uint32_t)i->cbObject) >> 16; + r->x.di = ((uint16_t)i->cbObject); + timestampns_to_dos_time(&r->x.cx, &r->x.dx, i->ModificationTime, data.tz_offset); +} + static int get_op_drive_num(union INTPACK __far *r) { DOSSFT __far *sft; @@ -527,6 +535,36 @@ static void handle_write(union INTPACK __far *r) clear_dos_err(r); } +static void handle_lock(union INTPACK __far *r) +{ + DOSSFT __far *sft = MK_FP(r->x.es, r->x.di); + unsigned openfile = get_sft_openfile_index(sft); + bool unlock = r->h.bl ? true : false; + unsigned numops = r->x.cx, i; + unsigned flags = (unlock ? SHFL_LOCK_CANCEL : SHFL_LOCK_EXCLUSIVE) + | SHFL_LOCK_WAIT | SHFL_LOCK_PARTIAL; + DOSLOCK __far *ops = MK_FP(r->x.ds, r->x.dx); + int32_t err; + + dlog_print("handle_lock "); + if (unlock) dlog_print("unlock"); + dlog_print(" numops="); + dlog_printu(numops); + dlog_endline(); + + for (i = 0; i < numops; i++) { + err = vbox_shfl_lock(&data.vb, data.hgcm_client_id, + data.files[openfile].root, data.files[openfile].handle, + ops[i].start_offset, ops[i].region_size, flags); + if (err) { + set_vbox_err(r, err); + return; + } + } + + clear_dos_err(r); +} + static void handle_close_all(union INTPACK __far *r) { int32_t err; @@ -574,6 +612,46 @@ static void handle_delete(union INTPACK __far *r) clear_dos_err(r); } + +static void handle_getattr(union INTPACK __far *r) +{ + const char __far *path = data.dossda->fn1; + int drive = drive_letter_to_index(path[0]); + SHFLROOT root = data.drives[drive].root; + int32_t err; + + dlog_print("handle_getattr "); + dlog_fprint(path); + dlog_endline(); + + copy_drive_relative_dirname(&shflstr.shflstr, path); + translate_filename_to_host(&shflstr.shflstr); + + memset(&createparms, 0, sizeof(SHFLCREATEPARMS)); + createparms.CreateFlags = SHFL_CF_LOOKUP; + + err = vbox_shfl_open(&data.vb, data.hgcm_client_id, root, + &shflstr.shflstr, &createparms); + if (err) { + set_vbox_err(r, err); + return; + } + switch (createparms.Result) { + case SHFL_PATH_NOT_FOUND: + set_dos_err(r, DOS_ERROR_PATH_NOT_FOUND); + return; + case SHFL_FILE_NOT_FOUND: + set_dos_err(r, DOS_ERROR_PATH_NOT_FOUND); + return; + default: + break; + } + + map_shfl_info_to_getattr(r, &createparms.Info); + clear_dos_err(r); +} + + static int32_t open_search_dir(SHFLROOT root, const char __far *path) { int32_t err; @@ -949,9 +1027,15 @@ static bool int2f_11_handler(union INTPACK r) case DOS_FN_WRITE: handle_write(&r); return true; + case DOS_FN_LOCK: + handle_lock(&r); + return true; case DOS_FN_DELETE: handle_delete(&r); return true; + case DOS_FN_GET_FILE_ATTR: + handle_getattr(&r); + return true; case DOS_FN_FIND_FIRST: case DOS_FN_FIND_NEXT: handle_find(&r); @@ -1267,6 +1267,25 @@ typedef struct _SHFLCREATEPARMS } SHFLCREATEPARMS; #pragma pack(pop) +/** Lock mode bit mask. */ +#define SHFL_LOCK_MODE_MASK (0x3) +/** Cancel lock on the given range. */ +#define SHFL_LOCK_CANCEL (0x0) +/** Acquire read only lock. Prevent write to the range. */ +#define SHFL_LOCK_SHARED (0x1) +/** Acquire write lock. Prevent both write and read to the range. */ +#define SHFL_LOCK_EXCLUSIVE (0x2) + +/** Do not wait for lock if it can not be acquired at the time. */ +#define SHFL_LOCK_NOWAIT (0x0) +/** Wait and acquire lock. */ +#define SHFL_LOCK_WAIT (0x4) + +/** Lock the specified range. */ +#define SHFL_LOCK_PARTIAL (0x0) +/** Lock entire object. */ +#define SHFL_LOCK_ENTIRE (0x8) + /** @name Shared Folders mappings. * @{ */ @@ -307,6 +307,43 @@ static int32_t vbox_shfl_write(LPVBOXCOMM vb, hgcm_client_id_t client_id, SHFLRO return req->header.result; } +static int32_t vbox_shfl_lock(LPVBOXCOMM vb, hgcm_client_id_t client_id, SHFLROOT root, SHFLHANDLE handle, + unsigned long offset, unsigned long length, unsigned flags) +{ + VMMDevHGCMCall __far *req = (void __far *) vb->buf; + vbox_hgcm_init_call(req, client_id, SHFL_FN_LOCK, 5); + + // arg 0 in uint32 "root" + req->aParms[0].type = VMMDevHGCMParmType_32bit; + req->aParms[0].u.value32 = root; + + // arg 1 in uint64 "handle" + req->aParms[1].type = VMMDevHGCMParmType_64bit; + req->aParms[1].u.value64 = handle; + + // arg 2 in uint64 "offset" + req->aParms[2].type = VMMDevHGCMParmType_64bit; + req->aParms[2].u.value64 = offset; + + // arg 3 inout uint64 "length" + req->aParms[3].type = VMMDevHGCMParmType_64bit; + req->aParms[3].u.value64 = length; + + // arg 4 in uint32 "flags" + req->aParms[4].type = VMMDevHGCMParmType_32bit; + req->aParms[4].u.value32 = flags; + + vbox_send_request(vb->iobase, vb->dds.physicalAddress); + + if (req->header.header.rc < 0) { + return req->header.header.rc; + } else if (req->header.header.rc == VINF_HGCM_ASYNC_EXECUTE) { + vbox_hgcm_wait(&req->header); + } + + return req->header.result; +} + static int32_t vbox_shfl_list(LPVBOXCOMM vb, hgcm_client_id_t client_id, SHFLROOT root, SHFLHANDLE handle, unsigned flags, unsigned __far *size, const SHFLSTRING *path, SHFLDIRINFO *dirinfo, unsigned __far *resume, unsigned __far *count) { |