diff options
| author | Javier <dev.git@javispedro.com> | 2022-04-20 23:50:37 +0200 | 
|---|---|---|
| committer | Javier <dev.git@javispedro.com> | 2022-04-20 23:50:37 +0200 | 
| commit | c53e746cfbc295aa72e12e1286d7ed7d0b13617a (patch) | |
| tree | a34f46d728d9cb10be96d69f13372e4165eb4f47 | |
| parent | c32d96aa6b92216d822933eaeb78aaef258dd92f (diff) | |
| download | vbados-c53e746cfbc295aa72e12e1286d7ed7d0b13617a.tar.gz vbados-c53e746cfbc295aa72e12e1286d7ed7d0b13617a.zip  | |
implement seek_end fn in vbsf
not used from DOS, as far as I can see, but windows may use it
| -rw-r--r-- | sftsr.c | 84 | ||||
| -rw-r--r-- | vboxshfl.h | 25 | 
2 files changed, 103 insertions, 6 deletions
@@ -35,6 +35,7 @@ static SHFLDIRINFO_WITH_NAME_BUF(shfldirinfo, SHFL_MAX_LEN);  static union {  	SHFLVOLINFO volinfo; +	SHFLFSOBJINFO objinfo;  	SHFLCREATEPARMS create;  } parms; @@ -604,6 +605,78 @@ static void handle_lock(union INTPACK __far *r)  	clear_dos_err(r);  } +static void handle_seek_end(union INTPACK __far *r) +{ +	DOSSFT __far *sft = MK_FP(r->x.es, r->x.di); +	unsigned openfile = get_sft_openfile_index(sft); +	uint8_t __far *buffer = data.dossda->cur_dta; +	long offset = ((uint32_t)(r->x.cx) << 16) | (uint32_t)(r->x.dx); +	unsigned buf_size = sizeof(SHFLFSOBJINFO); +	vboxerr err; + +	dlog_print("handle_seek_end offset="); +	dlog_printd(offset); +	dlog_endline(); + +	memset(&parms.objinfo, buf_size, sizeof(SHFLFSOBJINFO)); + +	// Get the current file size +	err = vbox_shfl_info(&data.vb, data.hgcm_client_id, +	                     data.files[openfile].root, data.files[openfile].handle, +	                     SHFL_INFO_GET | SHFL_INFO_FILE, &buf_size, &parms.objinfo); +	if (err) { +		set_vbox_err(r, err); +		return; +	} + +	if (!is_valid_dos_file(&parms.objinfo)) { +		// If for any reason the file grows to be too long, fail.. +		set_dos_err(r, DOS_ERROR_SEEK); +		return; +	} + +	// Update current file size +	sft->f_size = parms.objinfo.cbObject; + +	dlog_print("seek_end filesize="); +	dlog_printd(sft->f_size); +	dlog_endline(); + +	// Update the current offset pointer +	if (offset < 0 && sft->f_size < -offset ) { +		// Seeking beyond start of file +		set_dos_err(r, DOS_ERROR_SEEK); +		return; +	} else if (offset > 0) { +		dlog_puts("seek_end enlarge"); +		// Seeking past the end of the file, enlarge +		err = vbox_shfl_set_file_size(&data.vb, data.hgcm_client_id, +		                              data.files[openfile].root, data.files[openfile].handle, +		                              sft->f_size + offset); +		if (err) { +			set_vbox_err(r, err); +			return; +		} + +		// Update the file size again, and move the pointer to the end +		sft->f_size = sft->f_size + offset; +		sft->f_pos  = sft->f_size; +	} else { +		// Regular seek +		sft->f_pos = sft->f_size + offset; +	} + +	dlog_print("seek_end new pos="); +	dlog_printd(sft->f_pos); +	dlog_endline(); + +	// Return new file position in dx:ax +	r->x.dx = sft->f_pos >> 16; +	r->x.ax = sft->f_pos ; + +	clear_dos_err(r); +} +  static void handle_close_all(union INTPACK __far *r)  {  	vboxerr err; @@ -675,7 +748,7 @@ static void handle_rename(union INTPACK __far *r)  	copy_drive_relative_filename(&shflstr.shflstr, src);  	translate_filename_to_host(&shflstr.shflstr); -	// Reusing shfldirinfo buffer space here +	// Reusing shfldirinfo buffer space here for our second filename  	// Hoping no one does concurrent find_next and rename  	copy_drive_relative_filename(&shfldirinfo.dirinfo.name, dst);  	translate_filename_to_host(&shfldirinfo.dirinfo.name); @@ -1117,6 +1190,8 @@ static void handle_get_disk_free(union INTPACK __far *r)  	dlog_puts("handle disk free"); +	memset(&parms.volinfo, 0, sizeof(SHFLVOLINFO)); +  	// Ask VirtualBox for disk space info  	err = vbox_shfl_info(&data.vb, data.hgcm_client_id, root, SHFL_HANDLE_ROOT,  	                     SHFL_INFO_GET | SHFL_INFO_VOLUME, &buf_size, &parms.volinfo); @@ -1184,6 +1259,9 @@ static bool int2f_11_handler(union INTPACK r)  	case DOS_FN_LOCK:  		handle_lock(&r);  		return true; +	case DOS_FN_SEEK_END: +		handle_seek_end(&r); +		return true;  	case DOS_FN_DELETE:  		handle_delete(&r);  		return true; @@ -1209,10 +1287,6 @@ static bool int2f_11_handler(union INTPACK r)  	case DOS_FN_GET_DISK_FREE:  		handle_get_disk_free(&r);  		return true; -	case DOS_FN_SEEK_END: -		// I have no testcase for this function, so unsupported -		set_dos_err(&r, DOS_ERROR_INVALID_FUNCTION); -		return true;  	}  	return false; @@ -356,7 +356,7 @@ static vboxerr vbox_shfl_info(LPVBOXCOMM vb, hgcm_client_id_t client_id, SHFLROO  	// arg 3 inout uint32 "size"  	vbox_hgcm_set_parameter_uint32(req, 3, *size); -	// arg 4 in void "buffer" +	// arg 4 inout void "buffer"  	vbox_hgcm_set_parameter_pointer(req, 4, *size, buffer);  	if ((err = vbox_hgcm_do_call_sync(vb, req)) < 0) @@ -461,4 +461,27 @@ static vboxerr vbox_shfl_query_map_info(LPVBOXCOMM vb, hgcm_client_id_t client_i  	return req->header.result;  } +static vboxerr vbox_shfl_set_file_size(LPVBOXCOMM vb, hgcm_client_id_t client_id, +                                       SHFLROOT root, SHFLHANDLE handle, unsigned long size) +{ +	VMMDevHGCMCall __far *req = (void __far *) vb->buf; +	vboxerr err; + +	vbox_hgcm_init_call(req, client_id, SHFL_FN_SET_FILE_SIZE, 3); + +	// arg 0 in uint32 "root" +	vbox_hgcm_set_parameter_shflroot(req, 0, root); + +	// arg 1 in uint64 "handle" +	vbox_hgcm_set_parameter_shflhandle(req, 1, handle); + +	// arg 2 in uint64 "new_size" +	vbox_hgcm_set_parameter_uint32(req, 2, size); + +	if ((err = vbox_hgcm_do_call_sync(vb, req)) < 0) +		return err; + +	return req->header.result; +} +  #endif // VBOXSHFL_H  | 
