?? fsdiag.c
字號:
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
Diagnostics Packet Processing
General Description
Diagnostic packet processing routines for file system access.
Copyright (c) 1990-2003 by QUALCOMM, Incorporated. All Rights Reserved.
*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
/*===========================================================================
Edit History
$Header: //depot/asic/msmshared/services/diag/fsdiag.c#17 $
when who what, where, why
-------- --- ----------------------------------------------------------
02/18/04 as Fixed critical lint errors.
08/12/04 as Removed support for Remote file link.
06/23/04 as Fixes for RVCT 2.1
05/18/04 as Added security check to fsdiag_cmd.
11/05/03 pg Added support for fs_format function.
07/10/03 gr Moved access validation code into its own file.
06/23/07 jkl Featurized for EFS2.
04/07/03 jct Added file access validation callbacks which invoke a
registered callback for any file system access via
DIAG - the callback returns a status indicating whether or
not the operation may proceed. If no callback exists
the operation proceeds.
12/02/02 lad Added retry mechanism to read operation.
08/20/01 jal Updated for core VU
09/06/00 jal Incorporated David Brown's change to stop EFS file
descriptor leakage
05/10/00 lad Updated usage of diagpkt_shorten().
03/23/00 lad Fixed iterative listings.
02/28/00 lad Changed functions to use diagbuf allocation services.
01/20/99 lad Removed unnecessary debug MSG_MED calls.
11/16/99 lad Set attrib uses existing creation date if -1 is set.
fs_write overwrite fix.
07/23/99 lad Added rev 2 of EFS support.
03/26/99 lad Created for Embedded Filesystem (EFS) support. Write/MKDIR
===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
#include "comdef.h"
#include "customer.h"
#include "diagbuf.h"
#include "diagcmd.h"
#include "fsdiag.h"
#include "diag.h"
#include <string.h>
#include "fs.h"
/* Tell lint that we are OK with the fact that pkt_len and req are not
** used in some of the packets, as this is dictated by the awesome design */
/*lint -esym(715,pkt_len,req) */
/*--------------------------------------------------------
Gloabal data for cleanup of incomplete file transfers
--------------------------------------------------------*/
typedef enum
{
FSDIAG_NONE,
FSDIAG_READ,
FSDIAG_WRITE
} fsdiag_operation_enum_type;
LOCAL fsdiag_operation_enum_type fsdiag_op = FSDIAG_NONE;
LOCAL fs_handle_type fsdiag_handle = NULL;
LOCAL char fsdiag_filename[FSDIAG_MAX_FILENAME_LEN] = {'\0'};
/*===========================================================================
FUNCTION FSDIAG_CLEANUP
DESCRIPTION
This function cleans up (closes, etc) files operations that are were not
completed.
============================================================================*/
static boolean fsdiag_cleanup ()
{
boolean bRetVal = TRUE;
fs_rsp_msg_type fs_rsp; /* FS requires we specify a response message */
if (fsdiag_handle != NULL || fsdiag_filename[0] != NULL)
{
fs_close(fsdiag_handle, NULL, &fs_rsp);
if (fsdiag_op == FSDIAG_WRITE)
{
/*--------------------------------------------------------
Remove the stagnant file - if not same file, who cares.
--------------------------------------------------------*/
fs_remove(fsdiag_filename, NULL, &fs_rsp);
if (fs_rsp.rmfile.status != FS_OKAY_S)
{
bRetVal = FALSE;
}
}
}
/*---------------------------------------------
Initialize file handle and saved filename
---------------------------------------------*/
fsdiag_handle = NULL;
fsdiag_filename[0] = NULL;
fsdiag_op = FSDIAG_NONE;
return (bRetVal);
} /* fsdiag_cleanup */
/*===========================================================================
FUNCTION FSDIAG_MKDIR
DESCRIPTION
This function handles FS "Create Directory" commands in DIAG.
============================================================================*/
static PACKED void * fsdiag_mkdir (
fsdiag_mkdir_req_type *req,
word pkt_len
)
{
fs_rsp_msg_type fs_rsp; /* FS requires we specify a response message */
fsdiag_rsp_pkt_type *rsp;
const word rsp_len = FPOS(fsdiag_rsp_pkt_type, fs_rsp);
/*--------------------------------
Check for valid packet length.
--------------------------------*/
if (pkt_len != req->len + sizeof(req->len))
{
return (diagpkt_err_rsp(DIAG_BAD_LEN_F, req, pkt_len));
}
FS_DIAG_VALIDATE_ACCESS( MKDIR, (const char *)req->name );
rsp = (fsdiag_rsp_pkt_type *)diagpkt_alloc(DIAG_FS_OP_F, rsp_len);
/*--------------------------------
Check for valid filename length.
--------------------------------*/
fs_mkdir((const char *)req->name, NULL, &fs_rsp);
rsp->fs_status = fs_rsp.mkdir.status;
return (rsp);
} /* fsdiag_mkdir */
/*===========================================================================
FUNCTION FSDIAG_DISP_DIRS
DESCRIPTION
This function handles FS "Display Directory List" commands in DIAG.
============================================================================*/
static PACKED void *fsdiag_disp_dirs (
fsdiag_disp_dirs_req_type *req,
word pkt_len
)
{
fs_rsp_msg_type fs_rsp; /* FS requires we specify a response message */
fsdiag_rsp_pkt_type *rsp;
word rsp_len = FPOS(fsdiag_rsp_pkt_type, fs_rsp);
/*--------------------------------
Check for valid packet length.
--------------------------------*/
if (pkt_len != req->len + sizeof(req->len))
{
return (diagpkt_err_rsp(DIAG_BAD_LEN_F, req, pkt_len));
}
FS_DIAG_VALIDATE_ACCESS( DISP_DIRS, (const char *)req->name );
/*----------------------------------------------------------------
Unknown response size. Therefore, we will allocate the max
possible size for this packet and reduce length later.
----------------------------------------------------------------*/
rsp = (fsdiag_rsp_pkt_type *)diagpkt_alloc(DIAG_FS_OP_F, rsp_len + FSIZ(fsdiag_rsp_type, disp_dirs));
do
{
/*--------------------------------
Get the number of directories.
--------------------------------*/
/* Old versions of FS do not always properly set this variable */
fs_rsp.num_dirs.num_dirs = 0;
fs_num_dirs((const char *)req->name, NULL, &fs_rsp);
if (fs_rsp.num_dirs.status == FS_OKAY_S)
{
rsp->fs_rsp.disp_dirs.num_dirs = fs_rsp.num_dirs.num_dirs;
}
else
{
break;
}
/*-------------------------------------
Now get the actual directory list
--------------------------------------*/
fs_list_dirs((const char *)req->name,
(void*) rsp->fs_rsp.disp_dirs.dir_list.data,
FSDIAG_MAX_FILE_BLOCK_SIZE,
NULL,
&fs_rsp);
if (fs_rsp.list_dirs.status == FS_OKAY_S)
{
rsp->fs_rsp.disp_dirs.dir_list.len =
(word) fs_rsp.list_dirs.count;
rsp_len += sizeof(rsp->fs_rsp.disp_dirs.num_dirs) +
sizeof(rsp->fs_rsp.disp_dirs.dir_list.len) +
rsp->fs_rsp.disp_dirs.dir_list.len;
}
} while (0);
rsp->fs_status = fs_rsp.any.status;
/*------------------------------------------
If necessary, shorten the length of the
response to the actual size
------------------------------------------*/
diagpkt_shorten(rsp, rsp_len);
return (rsp);
} /* fsdiag_disp_dirs */
/*===========================================================================
FUNCTION FSDIAG_DISP_FILES
DESCRIPTION
This function handles FS "Display File List" commands in DIAG.
============================================================================*/
static PACKED void *fsdiag_disp_files (
fsdiag_disp_files_req_type *req,
word pkt_len
)
{
fs_rsp_msg_type fs_rsp; /* FS requires we specify a response message */
fsdiag_rsp_pkt_type *rsp;
word rsp_len = FPOS(fsdiag_rsp_pkt_type, fs_rsp);
/*--------------------------------
Check for valid packet length.
--------------------------------*/
if (pkt_len != req->len + sizeof(req->len))
{
return (diagpkt_err_rsp(DIAG_BAD_LEN_F, req, pkt_len));
}
FS_DIAG_VALIDATE_ACCESS( DISP_FILES, (const char *)req->name );
/*----------------------------------------------------------------
Unknown response size. Therefore, we will allocate the max
possible size for this packet and reduce length later.
----------------------------------------------------------------*/
rsp = (fsdiag_rsp_pkt_type *)diagpkt_alloc(DIAG_FS_OP_F, rsp_len + FSIZ(fsdiag_rsp_type, disp_files));
do
{
/*--------------------------------
Get the number of files.
--------------------------------*/
/* Old versions of FS don't always set this variable. */
fs_rsp.num_files.num_files = 0;
fs_num_files((const char *)req->name, NULL, &fs_rsp);
rsp->fs_status = fs_rsp.num_files.status;
if (fs_rsp.num_files.status == FS_OKAY_S)
{
rsp->fs_rsp.disp_files.num_files = fs_rsp.num_files.num_files;
}
else
{
break;
}
/*------------------------------
Now get the actual file list
-------------------------------*/
fs_list_files((const char *)req->name,
(void*) rsp->fs_rsp.disp_files.file_list.data,
FSDIAG_MAX_FILE_BLOCK_SIZE,
NULL,
&fs_rsp);
if (fs_rsp.list_files.status == FS_OKAY_S)
{
rsp->fs_rsp.disp_files.file_list.len =
(word) fs_rsp.list_files.count;
rsp_len += sizeof(rsp->fs_rsp.disp_files.num_files) +
sizeof(rsp->fs_rsp.disp_files.file_list.len) +
rsp->fs_rsp.disp_files.file_list.len;
}
} while (0);
rsp->fs_status = fs_rsp.any.status;
/*------------------------------------------
If necessary, shorten the length of the
response to the actual size
------------------------------------------*/
diagpkt_shorten(rsp, rsp_len);
return (rsp);
} /* fsdiag_disp_files */
/*===========================================================================
FUNCTION FSDIAG_RMDIR
DESCRIPTION
This function handles FS "Remove Directory" commands in DIAG.
============================================================================*/
static PACKED void *fsdiag_rmdir (
fsdiag_rmdir_req_type *req,
word pkt_len
)
{
fs_rsp_msg_type fs_rsp; /* FS requires we specify a response message */
fsdiag_rsp_pkt_type *rsp;
const word rsp_len = FPOS(fsdiag_rsp_pkt_type, fs_rsp);
/*--------------------------------
Check for valid packet length.
--------------------------------*/
if (pkt_len != req->len + sizeof(req->len))
{
return (diagpkt_err_rsp(DIAG_BAD_LEN_F, req, pkt_len));
}
FS_DIAG_VALIDATE_ACCESS( RMDIR, (const char *)req->name );
rsp = (fsdiag_rsp_pkt_type *)diagpkt_alloc(DIAG_FS_OP_F, rsp_len);
fs_rmdir((const char *)req->name, NULL, &fs_rsp);
rsp->fs_status = fs_rsp.rmdir.status;
return (rsp);
} /* fsdiag_rmdir */
/*===========================================================================
FUNCTION FSDIAG_GET_ATTRIB
DESCRIPTION
This function handles FS "Get File Attributes" commands in DIAG.
============================================================================*/
static PACKED void *fsdiag_get_attrib (
fsdiag_get_attrib_req_type *req,
word pkt_len
)
{
fs_rsp_msg_type fs_rsp; /* FS requires we specify a response message */
fsdiag_rsp_pkt_type *rsp;
word rsp_len = FPOS(fsdiag_rsp_pkt_type, fs_rsp);
/*--------------------------------
Check for valid packet length.
--------------------------------*/
if (pkt_len != req->len + sizeof(req->len))
{
return (diagpkt_err_rsp(DIAG_BAD_LEN_F, req, pkt_len));
}
FS_DIAG_VALIDATE_ACCESS( GET_ATTRIB, (const char *)req->name );
/*---------------------------------
Check for valid filename length.
---------------------------------*/
fs_get_file_attributes((const char *)req->name, NULL, &fs_rsp);
if (fs_rsp.get_attribs.status == FS_OKAY_S)
{
rsp_len += FSIZ(fsdiag_rsp_type, get_attrib);
}
rsp = (fsdiag_rsp_pkt_type *)diagpkt_alloc(DIAG_FS_OP_F, rsp_len);
rsp->fs_status = fs_rsp.get_attribs.status;
if (fs_rsp.get_attribs.status == FS_OKAY_S)
{
rsp->fs_rsp.get_attrib.attrib.attribute_mask =
fs_rsp.get_attribs.attributes;
rsp->fs_rsp.get_attrib.attrib.buffering_option =
fs_rsp.get_attribs.buffering_option;
rsp->fs_rsp.get_attrib.attrib.cleanup_option =
fs_rsp.get_attribs.cleanup_option;
rsp->fs_rsp.get_attrib.creation_date =
fs_rsp.get_attribs.creation_date;
/*------------------------------------------------
Event though it is not a attribute in the EFS,
file size would be a handy thing to know.
------------------------------------------------*/
fs_file_size((const char *)req->name, NULL, &fs_rsp);
if (fs_rsp.file_size.status == FS_OKAY_S)
{
rsp->fs_rsp.get_attrib.size = fs_rsp.file_size.size;
}
else
{
rsp->fs_rsp.get_attrib.size = 0;
}
}
return (rsp);
} /* fsdiag_get_attrib */
/*===========================================================================
FUNCTION FSDIAG_SET_ATTRIB
DESCRIPTION
This function handles FS SET ATTRIB commands in DIAG.
============================================================================*/
static PACKED void *fsdiag_set_attrib (
fsdiag_set_attrib_req_type *req,
word pkt_len
)
{
fs_rsp_msg_type fs_rsp; /* FS requires we specify a response message */
fsdiag_rsp_pkt_type *rsp;
const int rsp_len = FPOS(fsdiag_rsp_pkt_type, fs_rsp);
/*--------------------------------
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -