📄 fsdiag.c
字号:
Check for valid packet length.
--------------------------------*/
if (pkt_len != req->filename_info.len +
sizeof(req->filename_info.len) +
sizeof(req->creation_date) +
sizeof(req->attribs))
{
return (diagpkt_err_rsp(DIAG_BAD_LEN_F, req, pkt_len));
}
FS_DIAG_VALIDATE_ACCESS( SET_ATTRIB, (const char *)req->filename_info.name );
rsp = (fsdiag_rsp_pkt_type *) diagpkt_alloc (DIAG_FS_OP_F, rsp_len);
/*---------------------------------------------------------------
Since not all attributes will be externally settable via DIAG,
we need to get the existing attributes to set them back.
---------------------------------------------------------------*/
if (req->creation_date == 0xFFFFFFFF)
{
fs_get_attribs_rsp_type get_rsp;
fs_get_file_attributes((const char *)req->filename_info.name,
NULL,
(fs_rsp_msg_type *) &get_rsp);
if (get_rsp.status == FS_OKAY_S)
{
req->creation_date = get_rsp.creation_date;
}
else
{
rsp->fs_status = fs_rsp.set_attribs.status;
return (rsp);
}
}
fs_set_file_attributes(
(const char *)req->filename_info.name, /* Absolute dir name */
(fs_attribute_mask_type) req->attribs.attribute_mask,
(fs_file_date_type) req->creation_date,
(fs_buffering_option_type) req->attribs.buffering_option,
(fs_cleanup_option_type) req->attribs.cleanup_option,
NULL,
&fs_rsp);
rsp->fs_status = fs_rsp.set_attribs.status;
return (rsp);
} /* fsdiag_set_attrib */
/*===========================================================================
FUNCTION FSDIAG_READ
DESCRIPTION
This function handles FS read commands in DIAG.
============================================================================*/
static PACKED void *fsdiag_read (
fsdiag_read_req_type *req,
word pkt_len
)
{
fs_rsp_msg_type fs_rsp; /* Response from FS task */
fsdiag_data_block_type *data_ptr; /* Pointer to data block in packet */
static byte next_seq_num = 0; /* Expected next seqeunce number. */
static fs_file_position_type last_pos = 0xFFFFFFFF;
word expected_pkt_len; /* Used to calculate packet length */
fsdiag_rsp_pkt_type *rsp;
word rsp_len = FPOS(fsdiag_rsp_pkt_type, fs_rsp);
/* Keep progress stats
*/
static dword read_so_far;
static dword total_file_length;
fs_rsp.any.status = FS_FAIL_S; /* Init to be a generic failure. */
/* Do all error checking first
*/
if (req->seq_num == 0)
{
FS_DIAG_VALIDATE_ACCESS( READ, (const char *)req->filename_info.name );
/*--------------------------------
Check for valid packet length.
--------------------------------*/
expected_pkt_len =
sizeof(req->seq_num) +
sizeof(req->filename_info.len) +
req->filename_info.len;
if (pkt_len != expected_pkt_len)
{
return (diagpkt_err_rsp(DIAG_BAD_LEN_F, req, pkt_len));
}
}
else if (next_seq_num == req->seq_num)
{
/*--------------------------------
Check for valid packet length.
--------------------------------*/
expected_pkt_len = sizeof(req->seq_num);
if (pkt_len != expected_pkt_len)
{
fsdiag_cleanup();
next_seq_num = 0;
return (diagpkt_err_rsp(DIAG_BAD_LEN_F, req, pkt_len));
}
}
else /* Bad sequence number */
{
if (req->seq_num == (next_seq_num - 1) ||
((req->seq_num - next_seq_num) >= 254) ) // Trying a retry
{
// Set the next sequence number to the current seq number
next_seq_num = req->seq_num;
/* Reset the file position to last successful. */
fs_seek (fsdiag_handle, FS_SEEK_SET, last_pos, NULL, &fs_rsp);
if (fs_rsp.seek.status != FS_OKAY_S)
{
fsdiag_cleanup();
next_seq_num = 0;
return (diagpkt_err_rsp(DIAG_BAD_PARM_F, req, pkt_len));
}
}
else
{
fsdiag_cleanup();
next_seq_num = 0;
return (diagpkt_err_rsp(DIAG_BAD_PARM_F, req, pkt_len));
}
} /* if seq num 0 */
/*--------------------------------------
Allocate max size, then shorten later.
--------------------------------------*/
rsp = (fsdiag_rsp_pkt_type *)
diagpkt_alloc(DIAG_FS_OP_F, rsp_len + FSIZ(fsdiag_rsp_type, read));
rsp->fs_rsp.read.seq_num = req->seq_num;
/* Initialize to success */
fs_rsp.any.status = FS_OKAY_S;
/*-------------------------------------------------
Check if this is to start a new file
transfer, or continue an old one.
-------------------------------------------------*/
do
{
if (req->seq_num == 0)
{
/*---------------------------------------------
Initialize local vars.
---------------------------------------------*/
fsdiag_cleanup();
total_file_length = 0;
read_so_far = 0;
/*----------------------------
Open file for writing.
----------------------------*/
fs_open((const char *)req->filename_info.name, FS_OA_READONLY, NULL, NULL, &fs_rsp);
/* Save handle for subsequent reads */
if ((fsdiag_handle = fs_rsp.open.handle) == NULL ||
fs_rsp.any.status != FS_OKAY_S)
{
fsdiag_cleanup();
next_seq_num = 0;
rsp->fs_status = fs_rsp.open.status;
break;
}
else
{
last_pos = 0;
}
/*-----------------------------------------------
Save file name info for possible cleanup later
-----------------------------------------------*/
memcpy (fsdiag_filename,
(void *) req->filename_info.name,
req->filename_info.len);
/*-------------------------------------------
Store operation for open file for cleanup.
-------------------------------------------*/
fsdiag_op = FSDIAG_READ;
/*--------------------
Record total length
--------------------*/
fs_file_size(fsdiag_filename, NULL, &fs_rsp);
if (fs_rsp.file_size.status != FS_OKAY_S)
{
fsdiag_cleanup();
next_seq_num = 0;
rsp->fs_status = fs_rsp.file_size.status;
break;
}
rsp->fs_rsp.read.data.begin.total_length =
total_file_length = fs_rsp.file_size.size;
/*----------------------------------------
Update response length when successful
----------------------------------------*/
rsp_len += sizeof(rsp->fs_rsp.read.data.begin.total_length);
/*----------------------------------------
Set pointer to beginning of data block
----------------------------------------*/
data_ptr = (fsdiag_data_block_type*)
&rsp->fs_rsp.read.data.begin.block;
}
else /* Seqeunce num != 0 */
{
data_ptr = (fsdiag_data_block_type*)
&rsp->fs_rsp.read.data.block;
}
/* Record position prior to this read. */
fs_tell (fsdiag_handle, NULL, &fs_rsp);
if (fs_rsp.tell.status == FS_OKAY_S)
{
last_pos = fs_rsp.tell.position;
/* Go ahead and read. */
fs_read(fsdiag_handle,
(void*)&data_ptr->data,
FSDIAG_MAX_FILE_BLOCK_SIZE,
NULL,
&fs_rsp);
}
rsp->fs_status = fs_rsp.any.status;
if (fs_rsp.any.status != FS_OKAY_S)
{
fsdiag_cleanup();
next_seq_num = 0;
}
else
{
data_ptr->len = (word) fs_rsp.read.count;
/*--------------------------------------------------------------
Calculate response length. It already has the value for the
preliminary data such as status, so just add block length.
--------------------------------------------------------------*/
rsp_len += FPOS(fsdiag_read_rsp_type, data) +
data_ptr->len +
sizeof(data_ptr->len);
read_so_far += data_ptr->len;
/*----------------------------------------------------------
Check if we read an expected amount, and determine if we
need more blocks to complete the transfer.
----------------------------------------------------------*/
if (read_so_far < total_file_length)
{
rsp->fs_rsp.read.more = TRUE;
/* Must handle sequence number rollover */
next_seq_num = (next_seq_num == 0xFF) ? 1 : next_seq_num + 1;
}
else
{
rsp->fs_rsp.read.more = FALSE;
}
if (rsp->fs_rsp.read.more == FALSE)
{
fsdiag_cleanup();
next_seq_num = 0;
}
}
} while(0);
diagpkt_shorten(rsp, rsp_len);
return (rsp);
} /* fsdiag_read */
/*===========================================================================
FUNCTION FSDIAG_WRITE
DESCRIPTION
This function handles FS write commands in DIAG.
============================================================================*/
static PACKED void *fsdiag_write (
fsdiag_write_req_type *req,
word pkt_len
)
{
fs_open_xparms_type fs_open_xparms; /* Open and truncate parms */
fs_rsp_msg_type fs_rsp; /* Response from FS task */
fsdiag_data_block_type *data_ptr; /* Pointer to data block in packet */
static byte next_seq_num = 0; /* Expected next seqeunce number. */
word expected_pkt_len; /* Used to calculate packet length */
fsdiag_rsp_pkt_type *rsp;
word rsp_len = FPOS(fsdiag_rsp_pkt_type, fs_rsp) +
sizeof(fsdiag_write_rsp_type);
/*---------------------------------------------------
Keep progress stats for multiple packet operations
---------------------------------------------------*/
static dword written_so_far;
static dword total_file_length;
/*------------------------------
Do all error checking first
------------------------------*/
if (req->seq_num == 0)
{
FS_DIAG_VALIDATE_ACCESS( WRITE,
(const char *)req->block.begin.var_len_buf.name_info.name );
/*--------------------------------
Check for valid packet length.
--------------------------------*/
data_ptr = (fsdiag_data_block_type *)
&(req->block.begin.var_len_buf.raw_data[
req->block.begin.var_len_buf.name_info.len +
sizeof (req->block.begin.var_len_buf.name_info.len)]);
expected_pkt_len =
sizeof(req->seq_num) +
sizeof(req->more) +
sizeof(req->block.begin.mode) +
sizeof(req->block.begin.total_length) +
sizeof(req->block.begin.attrib) +
sizeof(req->block.begin.var_len_buf.name_info.len) +
req->block.begin.var_len_buf.name_info.len +
sizeof(data_ptr->len) +
data_ptr->len;
if (pkt_len != expected_pkt_len)
{
next_seq_num = 0;
return( diagpkt_err_rsp(DIAG_BAD_LEN_F, req, pkt_len) );
}
} /* Sequence number == 0 */
else if (next_seq_num == req->seq_num)
{
/*----------------------------------------
Assign data_ptr to request data block
----------------------------------------*/
data_ptr = &req->block.subseq;
/*--------------------------------
Check for valid packet length.
--------------------------------*/
expected_pkt_len = sizeof(req->seq_num) +
sizeof(req->more) +
sizeof(req->block.subseq.len) +
req->block.subseq.len;
if (pkt_len != expected_pkt_len)
{
next_seq_num = 0;
return( diagpkt_err_rsp(DIAG_BAD_LEN_F, req, pkt_len) );
}
}
else /* Bad sequence number */
{
fsdiag_cleanup();
next_seq_num = 0;
return( diagpkt_err_rsp(DIAG_BAD_PARM_F, req, pkt_len) );
}
rsp = (fsdiag_rsp_pkt_type *)diagpkt_alloc(DIAG_FS_OP_F, rsp_len);
rsp->fs_rsp.write.seq_num = req->seq_num;
/*------------------------------------------------------------------
For starters, check if this is to start a new file transfer, or
continue an old one. Also, verify packet length.
------------------------------------------------------------------*/
do
{
if (req->seq_num == 0)
{
/*---------------------------------------------------
Make sure the length of the data block is valid.
---------------------------------------------------*/
if (data_ptr->len > FSDIAG_MAX_FILE_BLOCK_SIZE)
{
fs_rsp.any.status = FS_PARAMETER_ERROR_S;
break;
}
/*------------------------------------------------------
We are starting a new file. Clean up any old files.
------------------------------------------------------*/
fsdiag_cleanup();
total_file_length = 0;
written_so_far = 0;
next_seq_num = 0;
/*----------------------------------------------
Set default attributes for new file.
External device may change attributes later.
----------------------------------------------*/
fs_open_xparms.create.attribute_mask =
(fs_attribute_mask_type) req->block.begin.attrib.attribute_mask;
fs_open_xparms.create.cleanup_option =
(fs_cleanup_option_type) req->block.begin.attrib.cleanup_option;
fs_open_xparms.create.buffering_option =
(fs_buffering_option_type) req->block.begin.attrib.buffering_option;
/*----------------------------
Open file for writing.
----------------------------*/
fs_open((const char *)req->block.begin.var_len_buf.name_info.name,
FS_OA_CREATE,
&fs_open_xparms,
NULL,
&fs_rsp);
/*----------------------------------------------
If overwrite option is specified, recover by
removing file and re-opening.
----------------------------------------------*/
if (fs_rsp.open.status == FS_FILE_ALREADY_EXISTS_S &&
req->block.begin.mode == FSDIAG_OVERWRITE)
{
fs_remove((const char *)req->block.begin.var_len_buf.name_info.name,
NULL,
&fs_rsp);
if (fs_rsp.rmfile.status == FS_OKAY_S)
{
/* Now try again */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -