aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--int21dos.h5
-rw-r--r--sftsr.c84
-rw-r--r--vboxdev.h19
-rw-r--r--vboxshfl.h37
4 files changed, 145 insertions, 0 deletions
diff --git a/int21dos.h b/int21dos.h
index f414216..a827b8f 100644
--- a/int21dos.h
+++ b/int21dos.h
@@ -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;
diff --git a/sftsr.c b/sftsr.c
index a5846c2..3f95323 100644
--- a/sftsr.c
+++ b/sftsr.c
@@ -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);
diff --git a/vboxdev.h b/vboxdev.h
index 93a0a7d..15db0e1 100644
--- a/vboxdev.h
+++ b/vboxdev.h
@@ -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.
* @{
*/
diff --git a/vboxshfl.h b/vboxshfl.h
index aef9bca..04afed0 100644
--- a/vboxshfl.h
+++ b/vboxshfl.h
@@ -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)
{