⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msdos_misc.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Miscellaneous routines implementation for MSDOS filesystem * *  Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia *  Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru> * *  The license and distribution terms for this file may be *  found in the file LICENSE in this distribution or at *  http://www.OARcorp.com/rtems/license.html. * *  @(#) $Id: msdos_misc.c,v 1.1.2.3 2005/10/06 12:10:58 joel Exp $ */#if HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#include <sys/time.h>#include <unistd.h>#include <string.h>#include <assert.h>#include <rtems/libio_.h>#include "fat.h"#include "fat_fat_operations.h"#include "fat_file.h"#include "msdos.h"/* msdos_get_token -- *     Routine to get a token (name or separator) from the path. * * PARAMETERS: *     path      - path to get token from *     ret_token - returned token *     token_len - length of returned token * * RETURNS: *     token type, token and token length  * */msdos_token_types_t msdos_get_token(const char *path, char *ret_token, int *token_len){    int                 rc = RC_OK;    register int        i = 0;    msdos_token_types_t type = MSDOS_NAME;    char                token[MSDOS_NAME_MAX_WITH_DOT+1];      register char       c;    /*      *  Copy a name into token.  (Remember NULL is a token.)     */    c = path[i];    while ( (!msdos_is_separator(c)) && (i <= MSDOS_NAME_MAX_WITH_DOT) )     {        token[i] = c;        if ( i == MSDOS_NAME_MAX_WITH_DOT )            return MSDOS_INVALID_TOKEN;        if ( !msdos_is_valid_name_char(c) )            return MSDOS_INVALID_TOKEN;           c = path [++i];    }    /*     *  Copy a seperator into token.     */    if ( i == 0 )     {        token[i] = c;        if ( token[i] != '\0' )         {            i++;            type = MSDOS_CURRENT_DIR;        }         else              type = MSDOS_NO_MORE_PATH;    }     else if (token[ i-1 ] != '\0')         token[i] = '\0';    /*     *  Set token_len to the number of characters copied.     */    *token_len = i;    /*     *  If we copied something that was not a seperator see if     *  it was a special name.     */    if ( type == MSDOS_NAME )     {        if ( strcmp( token, "..") == 0 )        {            strcpy(ret_token, MSDOS_DOTDOT_NAME);            type = MSDOS_UP_DIR;            return type;        }          if ( strcmp( token, "." ) == 0 )        {            strcpy(ret_token, MSDOS_DOT_NAME);            type = MSDOS_CURRENT_DIR;            return type;                }        rc = msdos_filename_unix2dos(token, *token_len, ret_token);        if ( rc != RC_OK )            return MSDOS_INVALID_TOKEN;         }    ret_token[MSDOS_NAME_MAX] = '\0';    return type;}/* msdos_find_name -- *     Find the node which correspondes to the name, open fat-file which  *     correspondes to the found node and close fat-file which correspondes  *     to the node we searched in. * * PARAMETERS: *     parent_loc - parent node description *     name       - name to find * * RETURNS: *     RC_OK and updated 'parent_loc' on success, or -1 if error  *     occured (errno set apropriately) * */int msdos_find_name(    rtems_filesystem_location_info_t *parent_loc,    char                             *name    ){    int              rc = RC_OK;    msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;    fat_file_fd_t   *fat_fd = NULL;    fat_auxiliary_t  aux;    unsigned short   time_val = 0;    unsigned short   date = 0;    unsigned char    node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];      memset(node_entry, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);      /*      * find the node which correspondes to the name in the directory pointed by      * 'parent_loc'     */    rc = msdos_get_name_node(parent_loc, name, &aux, node_entry);    if (rc != RC_OK)        return rc;    /* open fat-file corresponded to the found node */    rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);    if (rc != RC_OK)        return rc;      /*     * I don't like this if, but: we should do it , or should write new file      * size and first cluster num to the disk after each write operation      * (even if one byte is written  - that is TOO non-optimize) because      * otherwise real values of these fields stored in fat-file descriptor      * may be accidentely rewritten with wrong values stored on the disk     */    if (fat_fd->links_num == 1)    {        fat_fd->info_cln = aux.cln;        fat_fd->info_ofs = aux.ofs;        fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(node_entry);        fat_fd->first_char = *MSDOS_DIR_NAME(node_entry);            time_val = *MSDOS_DIR_WRITE_TIME(node_entry);        date = *MSDOS_DIR_WRITE_DATE(node_entry);            fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(time_val), CF_LE_W(date));         if ((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_DIRECTORY)        {            fat_fd->fat_file_type = FAT_DIRECTORY;            fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;                                                  rc = fat_file_size(parent_loc->mt_entry, fat_fd);            if (rc != RC_OK)            {                fat_file_close(parent_loc->mt_entry, fat_fd);                return rc;            }        }        else        {            fat_fd->fat_file_size = CF_LE_L(*MSDOS_DIR_FILE_SIZE(node_entry));             fat_fd->fat_file_type = FAT_FILE;                                                fat_fd->size_limit = MSDOS_MAX_FILE_SIZE;        }                /* these data is not actual for zero-length fat-file */        fat_fd->map.file_cln = 0;        fat_fd->map.disk_cln = fat_fd->cln;                if ((fat_fd->fat_file_size != 0) &&             (fat_fd->fat_file_size <= fs_info->fat.vol.bpc))        {            fat_fd->map.last_cln = fat_fd->cln;        }        else        {            fat_fd->map.last_cln = FAT_UNDEFINED_VALUE;        }    }      /* close fat-file corresponded to the node we searched in */    rc = fat_file_close(parent_loc->mt_entry, parent_loc->node_access);    if (rc != RC_OK)    {        fat_file_close(parent_loc->mt_entry, fat_fd);        return rc;    }    /* update node_info_ptr field */    parent_loc->node_access = fat_fd;      return rc;}  /* msdos_get_name_node -- *     This routine is used in two ways: for a new mode creation (a) or for *     search the node which correspondes to the name parameter (b). *     In case (a) 'name' should be set up to NULL and 'name_dir_entry' should  *     point to initialized 32 bytes structure described a new node.  *     In case (b) 'name' should contain a valid string. * *     (a): reading fat-file which correspondes to directory we are going to  *          create node in. If free slot is found write contents of  *          'name_dir_entry' into it. If reach end of fat-file and no free  *          slot found, write 32 bytes to the end of fat-file. * *     (b): reading fat-file which correspondes to directory and trying to  *          find slot with the name field == 'name' parameter * * * PARAMETERS: *     parent_loc     - node description to create node in or to find name in *     name           - NULL or name to find *     paux           - identify a node location on the disk - *                      cluster num and offset inside the cluster  *     name_dir_entry - node to create/placeholder for found node (IN/OUT) * * RETURNS: *     RC_OK, filled aux_struct_ptr and name_dir_entry on success, or -1 if  *     error occured (errno set apropriately) * */intmsdos_get_name_node(    rtems_filesystem_location_info_t *parent_loc,     char                             *name,     fat_auxiliary_t                  *paux,    char                             *name_dir_entry    ){    int              rc = RC_OK;    ssize_t          ret = 0;    msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;    fat_file_fd_t   *fat_fd = parent_loc->node_access;    unsigned32       dotdot_cln = 0;    /* find name in fat-file which correspondes to the directory */    rc = msdos_find_name_in_fat_file(parent_loc->mt_entry, fat_fd, name, paux,                                     name_dir_entry);    if ((rc != RC_OK) && (rc != MSDOS_NAME_NOT_FOUND_ERR))        return rc;      /* if we search for valid name and name not found -> return */    if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name != NULL))        return rc;      /*      * if we try to create new entry and the directory is not big enough      * currently - try to enlarge directory        */    if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name == NULL))    {        ret = fat_file_write(parent_loc->mt_entry, fat_fd,                              fat_fd->fat_file_size,                              MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,                              name_dir_entry);        if (ret == -1)            return -1;          /* on success directory is enlarged by a new cluster */        fat_fd->fat_file_size += fs_info->fat.vol.bpc;            /* get cluster num where a new node located */        rc = fat_file_ioctl(parent_loc->mt_entry, fat_fd, F_CLU_NUM,                            fat_fd->fat_file_size - 1, &paux->cln);                                if (rc != RC_OK)            return rc;        /*          * if new cluster allocated succesfully then new node is at very          * beginning of the cluster (offset is computed in bytes)          */        paux->ofs = 0;        return RC_OK;                                                     }                                                                          /*      * if we have deal with ".." - it is a special case :(((      *     * Really, we should return cluster num and offset not of ".." slot, but     * slot which correspondes to real directory name.     */    if ((rc == RC_OK) && (name != NULL))    {        if (strncmp(name, MSDOS_DOTDOT_NAME, MSDOS_SHORT_NAME_LEN) == 0)        {            dotdot_cln = MSDOS_EXTRACT_CLUSTER_NUM((name_dir_entry));            /* are we right under root dir ? */            if (dotdot_cln == 0)            {                 /*                  * we can relax about first_char field - it never should be                  * used for root dir                 */                paux->cln = FAT_ROOTDIR_CLUSTER_NUM;                paux->ofs = 0;            }              else            {                rc = msdos_get_dotdot_dir_info_cluster_num_and_offset(                        parent_loc->mt_entry,                        dotdot_cln,                        paux,                        name_dir_entry                        );                if (rc != RC_OK)                    return rc;            }        }      }    return rc;}/* * msdos_get_dotdot_dir_info_cluster_num_and_offset * * Unfortunately, in general, we cann't work here in fat-file ideologic  * (open fat_file "..", get ".." and ".", open "..", find an entry ...)  * because if we open * fat-file ".." it may happend that we have two different fat-file * descriptors ( for real name of directory and ".." name ) for a single  * file  ( cluster num of both pointers to the same cluster ) * But...we do it because we protected by semaphore *  *//* msdos_get_dotdot_dir_info_cluster_num_and_offset -- *     Get cluster num and offset not of ".." slot, but slot which correspondes  *     to real directory name.    * * PARAMETERS: *     mt_entry       - mount table entry *     cln            - data cluster num extracted drom ".." slot *     paux           - identify a node location on the disk - *                      number of cluster and offset inside the cluster *     dir_entry      - placeholder for found node  * * RETURNS: *     RC_OK, filled 'paux' and 'dir_entry' on success, or -1 if error occured *     (errno set apropriately) * */intmsdos_get_dotdot_dir_info_cluster_num_and_offset(    rtems_filesystem_mount_table_entry_t *mt_entry,     unsigned32                            cln,    fat_auxiliary_t                      *paux,    char                                 *dir_entry    ){    int              rc = RC_OK;    msdos_fs_info_t *fs_info = mt_entry->fs_info;    fat_file_fd_t   *fat_fd = NULL;    unsigned char    dot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];    unsigned char    dotdot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];    unsigned char    cur_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];    unsigned32       cl4find = 0;      memset(dot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);      memset(dotdot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);    memset(cur_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);      /*     * open fat-file corresponded to ".."     */    rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd);    if (rc != RC_OK)        return rc;      fat_fd->info_cln = paux->cln;    fat_fd->info_ofs = paux->ofs;    fat_fd->cln = cln;    fat_fd->fat_file_type = FAT_DIRECTORY;    fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;        fat_fd->map.file_cln = 0;    fat_fd->map.disk_cln = fat_fd->cln;    rc = fat_file_size(mt_entry, fat_fd);    if (rc != RC_OK)    {        fat_file_close(mt_entry, fat_fd);        return rc;    }        /* find "." node in opened directory */    rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOT_NAME, paux,                                      dot_node);                                       if (rc != RC_OK)    {        fat_file_close(mt_entry, fat_fd);        return rc;    }      /* find ".." node in opened directory */    rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOTDOT_NAME, paux,                                      dotdot_node);                                       if (rc != RC_OK)     {        fat_file_close(mt_entry, fat_fd);        return rc;    }    cl4find = MSDOS_EXTRACT_CLUSTER_NUM(dot_node);      /* close fat-file corresponded to ".." directory */    rc = fat_file_close(mt_entry, fat_fd);    if ( rc != RC_OK )        return rc;    if ( (MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0)    {        /*          * we handle root dir for all FAT types in the same way with the          * ordinary directories ( through fat_file_* calls )         */        paux->cln = FAT_ROOTDIR_CLUSTER_NUM;        paux->ofs = 0;    }    /* open fat-file corresponded to second ".." */    rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd);    if (rc != RC_OK)        return rc;    fat_fd->info_cln = paux->cln;    fat_fd->info_ofs = paux->ofs;    if ((MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0)        fat_fd->cln = fs_info->fat.vol.rdir_cl;    else        fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node);    fat_fd->fat_file_type = FAT_DIRECTORY;    fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -