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)  {  | 
