Changeset 07d6fd5 in rtems


Ignore:
Timestamp:
Apr 29, 2009, 8:31:27 AM (10 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
4.10, 4.11, master
Children:
164adec
Parents:
8c44190a
Message:

2009-04-29 Chris Johns <chrisj@…>

  • libcsupport/include/rtems/libio.h: Add rtems_off64_t for internal use. Update the internal off_t to the 64bit offset.
  • libnetworking/lib/ftpfs.c, libnetworking/lib/tftpDriver.c, libfs/src/nfsclient/src/nfs.c, libfs/src/imfs/imfs_fifo.c, libfs/src/imfs/memfile.c, libfs/src/imfs/imfs_directory.c, libfs/src/imfs/imfs.h, libfs/src/imfs/deviceio.c: Change off_t to rtems_off64_t.
  • libmisc/shell/main_msdosfmt.c: Add an info level so the format code can tell the user what is happening. Add more options to control the format configuration.
  • libfs/src/dosfs/msdos_format.c: Add a print function to display the format progress and print statements. Select a better default cluster size depending on the size of the disk. This lowers the size of the FAT on large disks. Read and maintain the MRB partition information.
  • libfs/src/dosfs/dosfs.h, libfs/src/dosfs/fat.h, libfs/src/dosfs/fat_file.c, libfs/src/dosfs/fat_file.h, libfs/src/dosfs/msdos.h, libfs/src/dosfs/msdos_conv.c, libfs/src/dosfs/msdos_create.c, libfs/src/dosfs/msdos_file.c, libfs/src/dosfs/msdos_handlers_dir.c, libfs/src/dosfs/msdos_handlers_file.c, libfs/src/dosfs/msdos_init.c, libfs/src/dosfs/msdos_initsupp.c, libfs/src/dosfs/msdos_misc.c, libfs/src/dosfs/msdos_mknod.c: Add long file name support. Change off_t to rtems_off64_t.
Location:
cpukit
Files:
27 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libcsupport/include/rtems/libio.h

    r8c44190a r07d6fd5  
    4141
    4242/*
     43 * A 64bit file offset for internal use by RTEMS. Based on the newlib type.
     44 */
     45typedef _off64_t rtems_off64_t;
     46
     47/*
    4348 * Valid RTEMS file types.
    4449 */
     
    8489);
    8590
    86 typedef off_t (*rtems_filesystem_lseek_t)(
     91typedef rtems_off64_t (*rtems_filesystem_lseek_t)(
    8792  rtems_libio_t *iop,
    88   off_t          length,
     93  rtems_off64_t  length,
    8994  int            whence
    9095);
     
    102107typedef int (*rtems_filesystem_ftruncate_t)(
    103108  rtems_libio_t *iop,
    104   off_t          length
     109  rtems_off64_t  length
    105110);
    106111
     
    348353struct rtems_libio_tt {
    349354    rtems_driver_name_t                    *driver;
    350     off_t                                   size;      /* size of file */
    351     off_t                                   offset;    /* current offset into file */
     355    rtems_off64_t                           size;      /* size of file */
     356    rtems_off64_t                           offset;    /* current offset into file */
    352357    uint32_t                                flags;
    353358    rtems_filesystem_location_info_t        pathinfo;
     
    367372typedef struct {
    368373    rtems_libio_t          *iop;
    369     off_t                   offset;
     374    rtems_off64_t           offset;
    370375    char                   *buffer;
    371376    uint32_t                count;
     
    442447);
    443448
    444 typedef int (*rtems_libio_lseek_t)(
    445   int    fd,
    446   off_t offset,
    447   int    whence
     449typedef rtems_off64_t (*rtems_libio_lseek_t)(
     450  int           fd,
     451  rtems_off64_t offset,
     452  int           whence
    448453);
    449454
  • cpukit/libfs/src/dosfs/dosfs.h

    r8c44190a r07d6fd5  
    3333#define MSDOS_FMT_FAT32  3
    3434
     35#define MSDOS_FMT_INFO_LEVEL_NONE   (0)
     36#define MSDOS_FMT_INFO_LEVEL_INFO   (1)
     37#define MSDOS_FMT_INFO_LEVEL_DETAIL (2)
     38#define MSDOS_FMT_INFO_LEVEL_DEBUG  (3)
     39
    3540/*
    3641 * data to be filled out for formatter: parameters for format call
     
    5257                                  /*   to be located at start of track     */
    5358                                  /*   or start of flash block             */
     59  int       info_level;           /* The amount of info to output          */
    5460} msdos_format_request_param_t;
    5561
  • cpukit/libfs/src/dosfs/fat.h

    r8c44190a r07d6fd5  
    251251#define FAT_GET_FSINFO_TRAIL_SIGNATURE(x)     FAT_GET_VAL32(x,508)
    252252#define FAT_SET_FSINFO_TRAIL_SIGNATURE(x,val) FAT_SET_VAL32(x,508,val)
    253 #define FAT_FSINFO_TRAIL_SIGNATURE_VALUE  (0x000055AA)
     253#define FAT_FSINFO_TRAIL_SIGNATURE_VALUE  (0xAA550000)
    254254/*
    255255 * I read FSInfo sector from offset 484 to access the information, so offsets
     
    352352
    353353/*
    354  * if the name we looking for is file we store not only first data cluster
    355  * number, but and cluster number and offset for directory entry for this
    356  * name
    357  */
    358 typedef struct fat_auxiliary_s
     354 * FAT position is a the cluster and the offset into the
     355 * cluster.
     356 */
     357typedef struct fat_pos_s
    359358{
    360359    uint32_t   cln;
    361360    uint32_t   ofs;
    362 } fat_auxiliary_t;
     361} fat_pos_t;
     362
     363/*
     364 * If the name we looking for is file we store not only first data cluster
     365 * number, but and cluster number and offset for directory entry for this
     366 * name. We also add the LFN start offset so we can delete it the whole
     367 * file name. We can then use this to delete the file.
     368 */
     369typedef struct fat_dir_pos_s
     370{
     371    fat_pos_t  sname;
     372    fat_pos_t  lname;
     373} fat_dir_pos_t;
     374
     375/*
     376 * Set the long name entries to this value for a short file name.
     377 */
     378#define FAT_FILE_SHORT_NAME (0xffffffff)
    363379
    364380#define FAT_FAT_OFFSET(fat_type, cln)                  \
     
    380396#define FAT_OP_TYPE_READ  0x1
    381397#define FAT_OP_TYPE_GET   0x2
     398
     399static inline void
     400fat_dir_pos_init(
     401    fat_dir_pos_t *dir_pos
     402    )
     403{
     404  dir_pos->sname.cln = 0;
     405  dir_pos->sname.ofs = 0;
     406  dir_pos->lname.cln = FAT_FILE_SHORT_NAME;
     407  dir_pos->lname.ofs = FAT_FILE_SHORT_NAME;
     408}
    382409
    383410static inline uint32_t
  • cpukit/libfs/src/dosfs/fat_file.c

    r8c44190a r07d6fd5  
    3434
    3535static inline void
    36 _hash_insert(Chain_Control *hash, uint32_t   key1, uint32_t   key2,
     36_hash_insert(rtems_chain_control *hash, uint32_t   key1, uint32_t   key2,
    3737             fat_file_fd_t *el);
    3838
    3939static inline void
    40 _hash_delete(Chain_Control *hash, uint32_t   key1, uint32_t   key2,
     40_hash_delete(rtems_chain_control *hash, uint32_t   key1, uint32_t   key2,
    4141             fat_file_fd_t *el);
    4242
     
    4444_hash_search(
    4545    rtems_filesystem_mount_table_entry_t  *mt_entry,
    46     Chain_Control                         *hash,
     46    rtems_chain_control                   *hash,
    4747    uint32_t                               key1,
    4848    uint32_t                               key2,
    49     fat_file_fd_t                          **ret
     49    fat_file_fd_t                                          **ret
    5050);
    5151
     
    7676 * PARAMETERS:
    7777 *     mt_entry - mount table entry
    78  *     cln      - cluster num of the node
    79  *     ofs      - offset of the node
     78 *     pos      - cluster and offset of the node
    8079 *     fat_fd   - placeholder for returned fat-file descriptor
    8180 *
     
    8786fat_file_open(
    8887    rtems_filesystem_mount_table_entry_t  *mt_entry,
    89     uint32_t                               cln,
    90     uint32_t                               ofs,
     88    fat_dir_pos_t                         *dir_pos,
    9189    fat_file_fd_t                        **fat_fd
    9290    )
     
    9896
    9997    /* construct key */
    100     key = fat_construct_key(mt_entry, cln, ofs);
     98    key = fat_construct_key(mt_entry, &dir_pos->sname);
    10199
    102100    /* access "valid" hash table */
     
    117115        rtems_set_errno_and_return_minus_one( ENOMEM );
    118116
     117    memset(lfat_fd, 0, sizeof(fat_file_fd_t));
     118   
    119119    lfat_fd->links_num = 1;
    120120    lfat_fd->flags &= ~FAT_FILE_REMOVED;
    121121    lfat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
     122
     123    lfat_fd->dir_pos = *dir_pos;
    122124
    123125    if ( rc != RC_OK )
     
    138140    }
    139141    _hash_insert(fs_info->vhash, key, lfat_fd->ino, lfat_fd);
    140 
    141142
    142143    /*
     
    204205    }
    205206
    206     key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
     207    key = fat_construct_key(mt_entry, &fat_fd->dir_pos.sname);
    207208
    208209    if (fat_fd->flags & FAT_FILE_REMOVED)
     
    583584    }
    584585
     586    fat_fd->fat_file_size = new_length;
     587   
    585588    return RC_OK;
    586589}
     
    737740    uint32_t       key = 0;
    738741
    739     key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
     742    key = fat_construct_key(mt_entry, &fat_fd->dir_pos.sname);
    740743
    741744    _hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
     
    870873 */
    871874static inline void
    872 _hash_insert(Chain_Control *hash, uint32_t   key1, uint32_t   key2,
     875_hash_insert(rtems_chain_control *hash, uint32_t   key1, uint32_t   key2,
    873876             fat_file_fd_t *el)
    874877{
    875     _Chain_Append((hash) + ((key1) % FAT_HASH_MODULE), &(el)->link);
     878    rtems_chain_append((hash) + ((key1) % FAT_HASH_MODULE), &(el)->link);
    876879}
    877880
     
    890893 */
    891894static inline void
    892 _hash_delete(Chain_Control *hash, uint32_t   key1, uint32_t   key2,
     895_hash_delete(rtems_chain_control *hash, uint32_t   key1, uint32_t   key2,
    893896             fat_file_fd_t *el)
    894897{
    895     _Chain_Extract(&(el)->link);
     898    rtems_chain_extract(&(el)->link);
    896899}
    897900
     
    913916_hash_search(
    914917    rtems_filesystem_mount_table_entry_t  *mt_entry,
    915     Chain_Control                         *hash,
     918    rtems_chain_control                   *hash,
    916919    uint32_t                               key1,
    917920    uint32_t                               key2,
     
    919922    )
    920923{
    921     uint32_t   mod = (key1) % FAT_HASH_MODULE;
    922     Chain_Node *the_node = ((Chain_Control *)((hash) + mod))->first;
    923 
    924     for ( ; !_Chain_Is_tail((hash) + mod, the_node) ; )
     924    uint32_t          mod = (key1) % FAT_HASH_MODULE;
     925    rtems_chain_node *the_node = ((rtems_chain_control *)((hash) + mod))->first;
     926
     927    for ( ; !rtems_chain_is_tail((hash) + mod, the_node) ; )
    925928    {
    926929        fat_file_fd_t *ffd = (fat_file_fd_t *)the_node;
    927         uint32_t   ck =
    928                 fat_construct_key(mt_entry, ffd->info_cln, ffd->info_ofs);
     930        uint32_t       ck =  fat_construct_key(mt_entry, &ffd->dir_pos.sname);
    929931
    930932        if ( (key1) == ck)
  • cpukit/libfs/src/dosfs/fat_file.h

    r8c44190a r07d6fd5  
    2020
    2121#include <time.h>
     22
     23#include "fat.h"
    2224
    2325#ifdef __cplusplus
     
    5860typedef struct fat_file_fd_s
    5961{
    60     Chain_Node      link;          /*
    61                                     * fat-file descriptors organized into hash;
    62                                     * collision lists are handled via link
    63                                     * field
    64                                     */
    65     uint32_t        links_num;     /*
    66                                     * the number of fat_file_open call on
    67                                     * this fat-file
    68                                     */
    69     uint32_t        ino;           /* inode, file serial number :)))) */
    70     fat_file_type_t fat_file_type;
    71     uint32_t        size_limit;
    72     uint32_t        fat_file_size; /* length  */
    73     uint32_t        info_cln;
    74     uint32_t        cln;
    75     uint16_t        info_ofs;
    76     unsigned char   first_char;
    77     uint8_t         flags;
    78     fat_file_map_t  map;
    79     time_t          mtime;
     62    rtems_chain_node link;          /*
     63                                     * fat-file descriptors organized into hash;
     64                                     * collision lists are handled via link
     65                                     * field
     66                                     */
     67    uint32_t         links_num;     /*
     68                                     * the number of fat_file_open call on
     69                                     * this fat-file
     70                                     */
     71    uint32_t         ino;           /* inode, file serial number :)))) */
     72    fat_file_type_t  fat_file_type;
     73    uint32_t         size_limit;
     74    uint32_t         fat_file_size; /* length  */
     75    uint32_t         cln;
     76    fat_dir_pos_t    dir_pos;
     77    uint8_t          flags;
     78    fat_file_map_t   map;
     79    time_t           mtime;
    8080
    8181} fat_file_fd_t;
    82 
    8382
    8483#define FAT_FILE_REMOVED  0x01
     
    102101
    103102#define FAT_FD_OF_ROOT_DIR(fat_fd)  \
    104   ((fat_fd->info_cln == FAT_ROOTDIR_CLUSTER_NUM ) && \
    105   (fat_fd->info_ofs == 0))
     103  ((fat_fd->dir_pos.sname.cln == FAT_ROOTDIR_CLUSTER_NUM) && \
     104  (fat_fd->dir_pos.sname.ofs == 0))
    106105
    107106#define FAT_EOF           0x00
     
    123122fat_construct_key(
    124123    rtems_filesystem_mount_table_entry_t *mt_entry,
    125     uint32_t                              cl,
    126     uint32_t                              ofs)
     124    fat_pos_t                            *pos)
    127125{
    128     return ( ((fat_cluster_num_to_sector512_num(mt_entry, cl) +
    129               (ofs >> FAT_SECTOR512_BITS)) << 4)              +
    130               ((ofs >> 5) & (FAT_DIRENTRIES_PER_SEC512 - 1)) );
     126    return ( ((fat_cluster_num_to_sector512_num(mt_entry, pos->cln) +
     127              (pos->ofs >> FAT_SECTOR512_BITS)) << 4)              +
     128              ((pos->ofs >> 5) & (FAT_DIRENTRIES_PER_SEC512 - 1)) );
    131129}
    132130
     
    134132int
    135133fat_file_open(rtems_filesystem_mount_table_entry_t  *mt_entry,
    136               uint32_t                               cln,
    137               uint32_t                               ofs,
     134              fat_dir_pos_t                         *dir_pos,
    138135              fat_file_fd_t                        **fat_fd);
    139136
  • cpukit/libfs/src/dosfs/msdos.h

    r8c44190a r07d6fd5  
    8585
    8686#define MSDOS_DIR_NAME(x)                 (char     *)((x) + 0)
     87#define MSDOS_DIR_ENTRY_TYPE(x)           (uint8_t  *)((x) + 0)
    8788#define MSDOS_DIR_ATTR(x)                 (uint8_t  *)((x) + 11)
    8889#define MSDOS_DIR_NT_RES(x)               (uint8_t  *)((x) + 12)
     90#define MSDOS_DIR_LFN_CHECKSUM(x)         (uint8_t  *)((x) + 13)
    8991#define MSDOS_DIR_CRT_TIME_TENTH(x)       (uint8_t  *)((x) + 13)
    9092#define MSDOS_DIR_CRT_TIME(x)             (uint16_t *)((x) + 14)
     
    122124#define MSDOS_ATTR_DIRECTORY    0x10
    123125#define MSDOS_ATTR_ARCHIVE      0x20
     126#define MSDOS_ATTR_LFN          (MSDOS_ATTR_READ_ONLY | \
     127                                 MSDOS_ATTR_HIDDEN | \
     128                                 MSDOS_ATTR_SYSTEM | \
     129                                 MSDOS_ATTR_VOLUME_ID)
     130#define MSDOS_ATTR_LFN_MASK     (MSDOS_ATTR_READ_ONLY | \
     131                                 MSDOS_ATTR_HIDDEN | \
     132                                 MSDOS_ATTR_SYSTEM | \
     133                                 MSDOS_ATTR_VOLUME_ID | \
     134                                 MSDOS_ATTR_DIRECTORY | \
     135                                 MSDOS_ATTR_ARCHIVE)
     136
     137#define MSDOS_LAST_LONG_ENTRY         0x40
     138#define MSDOS_LAST_LONG_ENTRY_MASK    0x3F
    124139
    125140#define MSDOS_DT_2SECONDS_MASK        0x1F    /* seconds divided by 2 */
     
    145160#define MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY    0x00
    146161
     162/*
     163 * Number of characters per directory entry for a long filename.
     164 */
     165#define MSDOS_LFN_LEN_PER_ENTRY (13)
    147166
    148167/*
    149168 *  Macros for names parsing and formatting
    150169 */
    151 #define msdos_is_valid_name_char(_ch)    (1)
    152170#define msdos_is_separator(_ch)          rtems_filesystem_is_separator(_ch)
    153171
     
    156174#define MSDOS_SHORT_NAME_LEN             (MSDOS_SHORT_BASE_LEN+\
    157175                                          MSDOS_SHORT_EXT_LEN) /* 11 chars */
     176#define MSDOS_NAME_MAX_LNF_LEN           (255)
    158177#define MSDOS_NAME_MAX                   MSDOS_SHORT_NAME_LEN
    159178#define MSDOS_NAME_MAX_WITH_DOT          (MSDOS_NAME_MAX + 1)
    160 
    161 #define MSDOS_DOT_NAME     ".          " /* ".", padded to MSDOS_NAME chars */
    162 #define MSDOS_DOTDOT_NAME  "..         " /* "..", padded to MSDOS_NAME chars */
     179#define MSDOS_NAME_MAX_LFN_WITH_DOT      (260)
     180
     181
     182extern const char const* MSDOS_DOT_NAME;    /* ".", padded to MSDOS_NAME chars */
     183extern const char const* MSDOS_DOTDOT_NAME; /* ".", padded to MSDOS_NAME chars */
     184
     185typedef enum msdos_name_types_e
     186{
     187    MSDOS_NAME_INVALID = 0, /* Unknown name type. Has invalid characters. */
     188    MSDOS_NAME_SHORT,       /* Name can be short. */
     189    MSDOS_NAME_LONG         /* Name is long; cannot be short. */
     190} msdos_name_type_t;
    163191
    164192typedef enum msdos_token_types_e
     
    259287);
    260288
    261 off_t msdos_file_lseek(
     289rtems_off64_t msdos_file_lseek(
    262290  rtems_libio_t        *iop,              /* IN  */
    263   off_t                 offset,           /* IN  */
     291  rtems_off64_t         offset,           /* IN  */
    264292  int                   whence            /* IN  */
    265293);
     
    273301msdos_file_ftruncate(
    274302  rtems_libio_t *iop,               /* IN  */
    275   off_t          length             /* IN  */
     303  rtems_off64_t  length            /* IN  */
    276304);
    277305
     
    284312  uint32_t       command,         /* IN  */
    285313  void          *buffer           /* IN  */
     314);
     315
     316int
     317msdos_dir_chmod(
     318  rtems_filesystem_location_info_t *pathloc, /* IN */
     319  mode_t                            mode     /* IN */
    286320);
    287321
     
    309343);
    310344
    311 off_t msdos_dir_lseek(
     345rtems_off64_t msdos_dir_lseek(
    312346  rtems_libio_t        *iop,              /* IN  */
    313   off_t                 offset,           /* IN  */
     347  rtems_off64_t         offset,           /* IN  */
    314348  int                   whence            /* IN  */
     349);
     350
     351int
     352msdos_file_chmod(
     353  rtems_filesystem_location_info_t *pathloc, /* IN */
     354  mode_t                            mode     /* IN */
    315355);
    316356
     
    325365
    326366int msdos_creat_node(rtems_filesystem_location_info_t  *parent_loc,
    327                  msdos_node_type_t                  type,
    328                  char                              *name,
    329                  mode_t                             mode,
    330                  const fat_file_fd_t               *link_fd);
     367                     msdos_node_type_t                  type,
     368                     const char                        *name,
     369                     int                                name_len,
     370                     mode_t                             mode,
     371                     const fat_file_fd_t               *link_fd);
    331372
    332373/* Misc prototypes */
    333 msdos_token_types_t msdos_get_token(const char *path,
    334                                     char       *token,
    335                                     int        *token_len);
     374msdos_token_types_t msdos_get_token(const char  *path,
     375                                    const char **token,
     376                                    int         *token_len);
    336377
    337378int msdos_find_name(
    338379  rtems_filesystem_location_info_t *parent_loc,
    339   char                             *name
     380  const char                       *name,
     381  int                               name_len
    340382);
    341383
    342384int msdos_get_name_node(
    343385  rtems_filesystem_location_info_t *parent_loc,
    344   char                             *name,
    345   fat_auxiliary_t                  *paux,
     386  bool                              create_node,
     387  const char                       *name,
     388  int                               name_len,
     389  msdos_name_type_t                 name_type,
     390  fat_dir_pos_t                    *dir_pos,
    346391  char                             *name_dir_entry
    347392);
     
    349394int msdos_dir_info_remove(rtems_filesystem_location_info_t *pathloc);
    350395
    351 int msdos_filename_unix2dos(char *un, int unlen, char *dn);
     396msdos_name_type_t msdos_long_to_short(const char *lfn, int lfn_len,
     397                                      char* sfn, int sfn_len);
     398
     399int msdos_filename_unix2dos(const char *un, int unlen, char *dn);
    352400
    353401void msdos_date_unix2dos(
     
    369417int msdos_set_first_char4file_name(
    370418  rtems_filesystem_mount_table_entry_t *mt_entry,
    371   uint32_t    cl,
    372   uint32_t    ofs,
    373   unsigned char first_char
     419  fat_dir_pos_t                        *dir_pos,
     420  unsigned char                         first_char
    374421);
    375422
     
    389436    rtems_filesystem_mount_table_entry_t *mt_entry,
    390437    fat_file_fd_t                        *fat_fd,
    391     char                                 *name,
    392     fat_auxiliary_t                      *paux,
     438    bool                                  create_node,
     439    const char                           *name,
     440    int                                   name_len,
     441    msdos_name_type_t                     name_type,
     442    fat_dir_pos_t                        *dir_pos,
    393443    char                                 *name_dir_entry
    394444);
     
    398448    fat_file_fd_t                        *fat_fd,
    399449    uint32_t                              cl4find,
    400     fat_auxiliary_t                      *paux,
     450    fat_dir_pos_t                        *dir_pos,
    401451    char                                 *dir_entry
    402452);
     
    405455    rtems_filesystem_mount_table_entry_t *mt_entry,
    406456    uint32_t                              cln,
    407     fat_auxiliary_t                      *paux,
     457    fat_dir_pos_t                        *dir_pos,
    408458    char                                 *dir_entry
    409459);
  • cpukit/libfs/src/dosfs/msdos_conv.c

    r8c44190a r07d6fd5  
    170170
    171171static const uint8_t msdos_map[] = {
     172    0,    0,    0,    0,    0,    0,    0,    0,    /* 00-07 */
     173    0,    0,    0,    0,    0,    0,    0,    0,    /* 08-0f */
     174    0,    0,    0,    0,    0,    0,    0,    0,    /* 10-17 */
     175    0,    0,    0,    0,    0,    0,    0,    0,    /* 18-1f */
     176    0,    '!',  0,    '#',  '$',  '%',  '&',  '\'', /* 20-27 */
     177    '(',  ')',  0,    '+',  0,    '-',  0,    0,    /* 28-2f */
     178    '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',  /* 30-37 */
     179    '8',  '9',  0,    0,    0,    0,    0,    0,    /* 38-3f */
     180    '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',  /* 40-47 */
     181    'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',  /* 48-4f */
     182    'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',  /* 50-57 */
     183    'X',  'Y',  'Z',  0,    0,    0,    '^',  '_',  /* 58-5f */
     184    '`',  'A',  'B',  'C',  'D',  'E',  'F',  'G',  /* 60-67 */
     185    'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',  /* 68-6f */
     186    'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',  /* 70-77 */
     187    'X',  'Y',  'Z',  '{',  0,    '}',  '~',  0,    /* 78-7f */
     188    0,    0,    0,    0,    0,    0,    0,    0,    /* 80-87 */
     189    0,    0,    0,    0,    0,    0,    0,    0,    /* 88-8f */
     190    0,    0,    0,    0,    0,    0,    0,    0,    /* 90-97 */
     191    0,    0,    0,    0,    0,    0,    0,    0,    /* 98-9f */
     192    0,    0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5, /* a0-a7 */
     193    0xf9, 0xb8, 0xa6, 0xae, 0xaa, 0xf0, 0xa9, 0xee, /* a8-af */
     194    0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa, /* b0-b7 */
     195    0xf7, 0xfb, 0xa7, 0xaf, 0xac, 0xab, 0xf3, 0xa8, /* b8-bf */
     196    0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* c0-c7 */
     197    0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* c8-cf */
     198    0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0x9e, /* d0-d7 */
     199    0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0xe1, /* d8-df */
     200    0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* e0-e7 */
     201    0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* e8-ef */
     202    0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0xf6, /* f0-f7 */
     203    0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0x98, /* f8-ff */
     204#if OLD_TABLE
    172205/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    173206/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     
    202235/* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    203236/* F8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     237#endif
    204238};
    205239/*
     
    208242 */
    209243int
    210 msdos_filename_unix2dos(char *un, int unlen, char *dn)
     244msdos_filename_unix2dos(const char *un, int unlen, char *dn)
    211245{
    212246        int i;
     
    234268        }
    235269
     270  /*
     271   * Remove any dots from the start of a file name.
     272   */
     273        while (unlen && (*un == '.')) {
     274                un++;
     275                unlen--;
     276        }
     277 
    236278        /*
    237279         * Copy the unix filename into the dos filename string upto the end
     
    241283         */
    242284        for (i = 0; i <= 7 && unlen && (c = *un) && c != '.'; i++) {
    243                 if ((dn[i] = msdos_map[c]) == 0)
    244                         return -1;
     285    if (msdos_map[c] == 0)
     286      break;
     287                dn[i] = msdos_map[c];
    245288                un++;
    246289                unlen--;
     
    265308         */
    266309        for (i = 8; i <= 10 && unlen && (c = *un); i++) {
    267                 if ((dn[i] = msdos_map[c]) == 0)
    268                         return -1;
     310    if (msdos_map[c] == 0)
     311      break;
     312    dn[i] = msdos_map[c];
    269313                un++;
    270314                unlen--;
  • cpukit/libfs/src/dosfs/msdos_create.c

    r8c44190a r07d6fd5  
    1818#include <errno.h>
    1919#include <assert.h>
     20#include <stdio.h>
    2021#include <stdlib.h>
    2122#include <string.h>
     
    3031
    3132/* msdos_creat_node --
    32  *     Create a new node. If a new node is file, FAT 32 Bytes Directory
     33 *     Create a new node. Determine if the name is a long name. If long we to
     34 *     scan the directory to create a short entry.
     35 *
     36 *
     37
     38
     39
     40 *     If a new node is file, FAT 32 Bytes Directory
    3341 *     Entry Structure is initialized, free space is found in parent
    3442 *     directory and structure is written to the disk. In case of directory,
     
    4957 */
    5058int
    51 msdos_creat_node(
    52     rtems_filesystem_location_info_t  *parent_loc,
    53     msdos_node_type_t                  type,
    54     char                              *name,
    55     mode_t                             mode,
    56     const fat_file_fd_t               *link_fd
    57     )
     59msdos_creat_node(rtems_filesystem_location_info_t  *parent_loc,
     60                 msdos_node_type_t                  type,
     61                 const char                        *name,
     62                 int                                name_len,
     63                 mode_t                             mode,
     64                 const fat_file_fd_t               *link_fd)
    5865{
    59     int              rc = RC_OK;
    60     ssize_t          ret = 0;
    61     msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
    62     fat_file_fd_t   *parent_fat_fd = parent_loc->node_access;
    63     fat_file_fd_t   *fat_fd = NULL;
    64     time_t           time_ret = 0;
    65     uint16_t         time_val = 0;
    66     uint16_t         date = 0;
    67     fat_auxiliary_t  aux;
    68     char             new_node  [MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
    69     char             dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
    70     char             link_node [MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
    71     uint32_t         sec = 0;
    72     uint32_t         byte = 0;
    73 
    74     memset(new_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
     66    int               rc = RC_OK;
     67    ssize_t           ret = 0;
     68    msdos_fs_info_t  *fs_info = parent_loc->mt_entry->fs_info;
     69    fat_file_fd_t    *parent_fat_fd = parent_loc->node_access;
     70    fat_file_fd_t    *fat_fd = NULL;
     71    time_t            time_ret = 0;
     72    uint16_t          time_val = 0;
     73    uint16_t          date = 0;
     74    fat_dir_pos_t     dir_pos;
     75    msdos_name_type_t name_type;
     76    char              short_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
     77    char              dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
     78    char              link_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
     79    uint32_t          sec = 0;
     80    uint32_t          byte = 0;
     81
     82    fat_dir_pos_init(&dir_pos);
     83   
     84    memset(short_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
    7585    memset(dot_dotdot, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2);
    7686
    77     /* set up name */
    78     strncpy(MSDOS_DIR_NAME(new_node), name, MSDOS_NAME_MAX);
     87    name_type = msdos_long_to_short (name, name_len,
     88                                     MSDOS_DIR_NAME(short_node),
     89                                     MSDOS_NAME_MAX);
    7990
    8091    /* fill reserved field */
    81     *MSDOS_DIR_NT_RES(new_node) = MSDOS_RES_NT_VALUE;
     92    *MSDOS_DIR_NT_RES(short_node) = MSDOS_RES_NT_VALUE;
    8293
    8394    /* set up last write date and time */
     
    8697        return -1;
    8798
    88     msdos_date_unix2dos(time_ret, &time_val, &date);
    89     *MSDOS_DIR_WRITE_TIME(new_node) = CT_LE_W(time_val);
    90     *MSDOS_DIR_WRITE_DATE(new_node) = CT_LE_W(date);
     99    msdos_date_unix2dos(time_ret, &date, &time_val);
     100    *MSDOS_DIR_WRITE_TIME(short_node) = CT_LE_W(time_val);
     101    *MSDOS_DIR_WRITE_DATE(short_node) = CT_LE_W(date);
    91102
    92103    /* initialize directory/file size */
    93     *MSDOS_DIR_FILE_SIZE(new_node) = MSDOS_INIT_DIR_SIZE;
    94 
    95     if (type == MSDOS_DIRECTORY){
    96         *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_DIRECTORY;
     104    *MSDOS_DIR_FILE_SIZE(short_node) = MSDOS_INIT_DIR_SIZE;
     105
     106    if (type == MSDOS_DIRECTORY) {
     107      *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_DIRECTORY;
    97108    }
    98109    else if (type == MSDOS_HARD_LINK) {
     
    106117       */
    107118      sec = fat_cluster_num_to_sector_num(parent_loc->mt_entry,
    108                                           link_fd->info_cln);
    109       sec += (link_fd->info_ofs >> fs_info->fat.vol.sec_log2);
    110       byte = (link_fd->info_ofs & (fs_info->fat.vol.bps - 1));
     119                                          link_fd->dir_pos.sname.cln);
     120      sec += (link_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
     121      byte = (link_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1));
    111122
    112123      ret = _fat_block_read(parent_loc->mt_entry,
    113                             sec, byte, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
     124                            sec, byte, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
    114125                            link_node);
    115126      if (ret < 0) {
    116         return -1;
     127          return -1;
    117128      }
    118129      /*
    119130       * copy various attributes
    120131       */
    121       *MSDOS_DIR_ATTR(new_node)          =*MSDOS_DIR_ATTR(link_node);
    122       *MSDOS_DIR_CRT_TIME_TENTH(new_node)=*MSDOS_DIR_CRT_TIME_TENTH(link_node);
    123       *MSDOS_DIR_CRT_TIME(new_node)      =*MSDOS_DIR_CRT_TIME(link_node);
    124       *MSDOS_DIR_CRT_DATE(new_node)      =*MSDOS_DIR_CRT_DATE(link_node);
     132      *MSDOS_DIR_ATTR(short_node)          =*MSDOS_DIR_ATTR(link_node);
     133      *MSDOS_DIR_CRT_TIME_TENTH(short_node)=*MSDOS_DIR_CRT_TIME_TENTH(link_node);
     134      *MSDOS_DIR_CRT_TIME(short_node)      =*MSDOS_DIR_CRT_TIME(link_node);
     135      *MSDOS_DIR_CRT_DATE(short_node)      =*MSDOS_DIR_CRT_DATE(link_node);
    125136
    126137      /*
    127138       * copy/set "file size", "first cluster"
    128139       */
    129       *MSDOS_DIR_FILE_SIZE(new_node)     =*MSDOS_DIR_FILE_SIZE(link_node);
    130 
    131       *MSDOS_DIR_FIRST_CLUSTER_LOW(new_node) =
     140      *MSDOS_DIR_FILE_SIZE(short_node)     =*MSDOS_DIR_FILE_SIZE(link_node);
     141
     142      *MSDOS_DIR_FIRST_CLUSTER_LOW(short_node) =
    132143           *MSDOS_DIR_FIRST_CLUSTER_LOW(link_node);
    133       *MSDOS_DIR_FIRST_CLUSTER_HI(new_node) =
     144      *MSDOS_DIR_FIRST_CLUSTER_HI(short_node) =
    134145           *MSDOS_DIR_FIRST_CLUSTER_HI(link_node);
    135146      /*
    136147       * set "archive bit" due to changes
    137148       */
    138       *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
     149      *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_ARCHIVE;
    139150      /*
    140151       * set "last access" date to today
    141152       */
    142       *MSDOS_DIR_LAST_ACCESS_DATE(new_node) = CT_LE_W(date);
     153      *MSDOS_DIR_LAST_ACCESS_DATE(short_node) = CT_LE_W(date);
    143154    }
    144155    else { /* regular file... */
    145         *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
     156        *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_ARCHIVE;
    146157    }
    147158
     
    150161     * FAT 32 Bytes Directory Entry Structure to the disk
    151162     */
    152     rc = msdos_get_name_node(parent_loc, NULL, &aux, new_node);
     163    rc = msdos_get_name_node(parent_loc, true, name, name_len,
     164                             name_type, &dir_pos, short_node);
    153165    if ( rc != RC_OK )
    154166        return rc;
     
    161173    {
    162174        /* open new directory as fat-file */
    163         rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
     175        rc = fat_file_open(parent_loc->mt_entry, &dir_pos, &fat_fd);
    164176        if (rc != RC_OK)
    165177            goto err;
     
    169181         * descritor
    170182         */
    171         fat_fd->info_cln = aux.cln;
    172         fat_fd->info_ofs = aux.ofs;
    173183        fat_fd->fat_file_size = 0;
    174184        fat_fd->fat_file_type = FAT_DIRECTORY;
     
    179189         * names
    180190         */
    181         memcpy(DOT_NODE_P(dot_dotdot), new_node,
     191        memcpy(DOT_NODE_P(dot_dotdot), short_node,
    182192               MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
    183         memcpy(DOTDOT_NODE_P(dot_dotdot), new_node,
     193        memcpy(DOTDOT_NODE_P(dot_dotdot), short_node,
    184194               MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
    185195        memcpy(MSDOS_DIR_NAME(DOT_NODE_P(dot_dotdot)), MSDOS_DOT_NAME,
     
    254264
    255265err:
    256     /* mark 32bytes structure on the disk as free */
    257     msdos_set_first_char4file_name(parent_loc->mt_entry, aux.cln, aux.ofs,
    258                                    0xE5);
     266    /* mark the used 32bytes structure on the disk as free */
     267    msdos_set_first_char4file_name(parent_loc->mt_entry, &dir_pos, 0xE5);
    259268    return rc;
    260269}
     
    288297int
    289298msdos_file_link(rtems_filesystem_location_info_t *to_loc,
    290                 rtems_filesystem_location_info_t *par_loc,
    291                 const char                       *token
     299                rtems_filesystem_location_info_t *par_loc,
     300                const char                       *name
    292301)
    293302{
     
    296305    msdos_fs_info_t   *fs_info     = to_loc->mt_entry->fs_info;
    297306    fat_file_fd_t     *to_fat_fd   = to_loc->node_access;
    298     char               new_name[ MSDOS_NAME_MAX + 1 ];
     307    const char        *token;
    299308    int                len;
    300309
     
    302311     * check spelling and format new node name
    303312     */
    304     if (MSDOS_NAME != msdos_get_token(token, new_name, &len)) {
     313    if (MSDOS_NAME != msdos_get_token(name, &token, &len)) {
    305314      rtems_set_errno_and_return_minus_one(ENAMETOOLONG);
    306315    }
     
    325334     * copying relevant info from existing file
    326335     */
    327     rc = msdos_creat_node(par_loc,MSDOS_HARD_LINK,new_name,S_IFREG,
    328                           to_loc->node_access);
     336    rc = msdos_creat_node(par_loc,MSDOS_HARD_LINK,name,len,S_IFREG,
     337                          to_loc->node_access);
    329338    /*
    330339     * set file size and first cluster number of old entry to 0
  • cpukit/libfs/src/dosfs/msdos_dir.c

    r8c44190a r07d6fd5  
    1515#endif
    1616
     17#include <ctype.h>
    1718#include <stdlib.h>
    1819#include <unistd.h>
     
    146147  len = i;
    147148  while (i-- > 0) {
    148     *dst++ = *src_tmp++;
     149    *dst++ = tolower(*src_tmp++);
    149150  }
    150151  /*
     
    165166    src_tmp = src + MSDOS_SHORT_BASE_LEN;
    166167    while (i-- > 0) {
    167       *dst++ = *src_tmp++;
     168      *dst++ = tolower(*src_tmp++);
    168169      len++;
    169170    }
     
    211212    uint32_t           bts2rd = 0;
    212213    uint32_t           cur_cln = 0;
     214    uint32_t           lfn_start = FAT_FILE_SHORT_NAME;
     215    uint8_t            lfn_checksum = 0;
     216    int                lfn_entries = 0;
    213217
    214218    /*
     
    254258        for (i = 0; i < ret; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
    255259        {
    256             if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
     260            char* entry = (char*) fs_info->cl_buf + i;
     261           
     262            /*
     263             * Is this directory from here on empty ?
     264             */
     265            if ((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
    257266                MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
    258267            {
     
    261270            }
    262271
    263             /* have to look at the DIR_NAME as "raw" 8-bit data */
    264             if ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
    265                 MSDOS_THIS_DIR_ENTRY_EMPTY)
     272            /* Is the directory entry empty */
     273            if ((*MSDOS_DIR_ENTRY_TYPE(entry)) == MSDOS_THIS_DIR_ENTRY_EMPTY)
    266274                continue;
    267275
     276            /* Is the directory entry empty a volume label */
     277            if (((*MSDOS_DIR_ATTR(entry)) & MSDOS_ATTR_VOLUME_ID) &&
     278                ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) != MSDOS_ATTR_LFN))
     279                continue;
     280
    268281            /*
    269              * skip active entries until get the entry to start from
     282             * Check the attribute to see if the entry is for a long file
     283             * name.
    270284             */
    271             if (start)
     285            if ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) ==
     286                MSDOS_ATTR_LFN)
    272287            {
    273                 start--;
    274                 continue;
     288                int   o;
     289                char* p;
     290                int   q;
     291               
     292                /*
     293                 * Is this is the first entry of a LFN ?
     294                 */
     295                if (lfn_start == FAT_FILE_SHORT_NAME)
     296                {
     297                    /*
     298                     * The first entry must have the last long entry flag set.
     299                     */
     300                    if ((*MSDOS_DIR_ENTRY_TYPE(entry) &
     301                         MSDOS_LAST_LONG_ENTRY) == 0)
     302                        continue;
     303
     304                    /*
     305                     * Remember the start location of the long file name.
     306                     */
     307                    lfn_start =
     308                      ((j * bts2rd) + i) / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
     309                   
     310                    /*
     311                     * Get the number of entries so we can count down and
     312                     * also the checksum of the short entry.
     313                     */
     314                    lfn_entries = (*MSDOS_DIR_ENTRY_TYPE(entry) &
     315                                   MSDOS_LAST_LONG_ENTRY_MASK);
     316                    lfn_checksum = *MSDOS_DIR_LFN_CHECKSUM(entry);
     317                    memset (tmp_dirent.d_name, 0, sizeof(tmp_dirent.d_name));
     318                }
     319
     320                /*
     321                 * If the entry number or the check sum do not match
     322                 * forget this series of long directory entries. These could
     323                 * be orphaned entries depending on the history of the
     324                 * disk.
     325                 */
     326                if ((lfn_entries != (*MSDOS_DIR_ENTRY_TYPE(entry) &
     327                                     MSDOS_LAST_LONG_ENTRY_MASK)) ||
     328                    (lfn_checksum != *MSDOS_DIR_LFN_CHECKSUM(entry)))
     329                {
     330                    lfn_start = FAT_FILE_SHORT_NAME;
     331                    continue;
     332                }
     333             
     334                /*
     335                 * Extract the file name into the directory entry. The data is
     336                 * stored in UNICODE characters (16bit). No translation is
     337                 * currently supported.
     338                 *
     339                 * The DOS maximum length is 255 characters without the
     340                 * trailing nul character. We need to range check the length to
     341                 * fit in the directory entry name field.
     342                 */
     343               
     344                lfn_entries--;
     345                p = entry + 1;
     346                o = lfn_entries * MSDOS_LFN_LEN_PER_ENTRY;
     347               
     348                for (q = 0; q < MSDOS_LFN_LEN_PER_ENTRY; q++)
     349                {
     350                    if (o >= (sizeof(tmp_dirent.d_name) - 1))
     351                        break;
     352                       
     353                    tmp_dirent.d_name[o++] = *p;
     354
     355                    if (*p == '\0')
     356                        break;
     357
     358                    switch (q)
     359                    {
     360                        case 4:
     361                            p += 5;
     362                            break;
     363                        case 10:
     364                            p += 4;
     365                            break;
     366                        default:
     367                            p += 2;
     368                            break;
     369                    }
     370                }
    275371            }
    276 
    277             /*
    278              * Move the entry to the return buffer
    279              *
    280              * unfortunately there is no method to extract ino except to
    281              * open fat-file descriptor :( ... so, open it
    282              */
    283 
    284             /* get number of cluster we are working with */
    285             rc = fat_file_ioctl(iop->pathinfo.mt_entry, fat_fd, F_CLU_NUM,
    286                                 j * bts2rd, &cur_cln);
    287             if (rc != RC_OK)
     372            else
    288373            {
    289                 rtems_semaphore_release(fs_info->vol_sema);
    290                 return rc;
     374                fat_dir_pos_t dir_pos;
     375             
     376                /*
     377                 * Skip active entries until get the entry to start from.
     378                 */
     379                if (start)
     380                {
     381                    lfn_start = FAT_FILE_SHORT_NAME;
     382                    start--;
     383                    continue;
     384                }
     385
     386                /*
     387                 * Move the entry to the return buffer
     388                 *
     389                 * unfortunately there is no method to extract ino except to
     390                 * open fat-file descriptor :( ... so, open it
     391                 */
     392
     393                /* get number of cluster we are working with */
     394                rc = fat_file_ioctl(iop->pathinfo.mt_entry, fat_fd, F_CLU_NUM,
     395                                    j * bts2rd, &cur_cln);
     396                if (rc != RC_OK)
     397                {
     398                    rtems_semaphore_release(fs_info->vol_sema);
     399                    return rc;
     400                }
     401
     402                fat_dir_pos_init(&dir_pos);
     403                dir_pos.sname.cln = cur_cln;
     404                dir_pos.sname.ofs = i;
     405                rc = fat_file_open(iop->pathinfo.mt_entry, &dir_pos, &tmp_fat_fd);
     406                if (rc != RC_OK)
     407                {
     408                    rtems_semaphore_release(fs_info->vol_sema);
     409                    return rc;
     410                }
     411
     412                /* fill in dirent structure */
     413                /* XXX: from what and in what d_off should be computed ?! */
     414                tmp_dirent.d_off = start + cmpltd;
     415                tmp_dirent.d_reclen = sizeof(struct dirent);
     416                tmp_dirent.d_ino = tmp_fat_fd->ino;
     417
     418                /*
     419                 * If a long file name check if the correct number of
     420                 * entries have been found and if the checksum is correct.
     421                 * If not return the short file name.
     422                 */
     423                if (lfn_start != FAT_FILE_SHORT_NAME)
     424                {
     425                    uint8_t  cs = 0;
     426                    uint8_t* p = (uint8_t*) entry;
     427                    int      i;
     428
     429                    for (i = 0; i < 11; i++, p++)
     430                        cs = ((cs & 1) ? 0x80 : 0) + (cs >> 1) + *p;
     431
     432                    if (lfn_entries || (lfn_checksum != cs))
     433                        lfn_start = FAT_FILE_SHORT_NAME;
     434                }
     435
     436                if (lfn_start == FAT_FILE_SHORT_NAME)
     437                {
     438                    /*
     439                     * convert dir entry from fixed 8+3 format (without dot)
     440                     * to 0..8 + 1dot + 0..3 format
     441                     */
     442                    tmp_dirent.d_namlen = msdos_format_dirent_with_dot(
     443                        tmp_dirent.d_name, entry); /* src text */
     444                }
     445                else
     446                {
     447                    tmp_dirent.d_namlen = strlen(tmp_dirent.d_name);
     448                }
     449               
     450                memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
     451
     452                iop->offset = iop->offset + sizeof(struct dirent);
     453                cmpltd += (sizeof(struct dirent));
     454                count -= (sizeof(struct dirent));
     455
     456                /* inode number extracted, close fat-file */
     457                rc = fat_file_close(iop->pathinfo.mt_entry, tmp_fat_fd);
     458                if (rc != RC_OK)
     459                {
     460                    rtems_semaphore_release(fs_info->vol_sema);
     461                    return rc;
     462                }
    291463            }
    292 
    293             rc = fat_file_open(iop->pathinfo.mt_entry, cur_cln, i,
    294                                &tmp_fat_fd);
    295             if (rc != RC_OK)
    296             {
    297                 rtems_semaphore_release(fs_info->vol_sema);
    298                 return rc;
    299             }
    300 
    301             tmp_fat_fd->info_cln = cur_cln;
    302             tmp_fat_fd->info_ofs = i;
    303 
    304             /* fill in dirent structure */
    305             /* XXX: from what and in what d_off should be computed ?! */
    306             tmp_dirent.d_off = start + cmpltd;
    307             tmp_dirent.d_reclen = sizeof(struct dirent);
    308             tmp_dirent.d_ino = tmp_fat_fd->ino;
    309             /*
    310              * convert dir entry from fixed 8+3 format (without dot)
    311              * to 0..8 + 1dot + 0..3 format
    312              */
    313             tmp_dirent.d_namlen = msdos_format_dirent_with_dot(
    314               tmp_dirent.d_name,
    315               (char *) fs_info->cl_buf + i); /* src text */
    316             memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
    317 
    318             iop->offset = iop->offset + sizeof(struct dirent);
    319             cmpltd += (sizeof(struct dirent));
    320             count -= (sizeof(struct dirent));
    321 
    322             /* inode number extracted, close fat-file */
    323             rc = fat_file_close(iop->pathinfo.mt_entry, tmp_fat_fd);
    324             if (rc != RC_OK)
    325             {
    326                 rtems_semaphore_release(fs_info->vol_sema);
    327                 return rc;
    328             }
    329 
     464           
    330465            if (count <= 0)
    331466                break;
     
    364499 *     set apropriately).
    365500 */
    366 off_t
    367 msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence)
     501rtems_off64_t
     502msdos_dir_lseek(rtems_libio_t *iop, rtems_off64_t offset, int whence)
    368503{
    369504    switch (whence)
     
    472607}
    473608
     609/* msdos_dir_chmod --
     610 *     Change the attributes of the directory. This currently does
     611 *     nothing and returns no error.
     612 *
     613 * PARAMETERS:
     614 *     pathloc - node description
     615 *     mode - the new mode
     616 *
     617 * RETURNS:
     618 *     RC_OK always
     619 */
     620int
     621msdos_dir_chmod(rtems_filesystem_location_info_t *pathloc,
     622                mode_t                            mode)
     623{
     624  return RC_OK;
     625}
     626
    474627/* msdos_dir_rmnod --
    475628 *     Remove directory node.
     
    499652
    500653    /*
    501      * We deny attemp to delete open directory (if directory is current
     654     * We deny attempts to delete open directory (if directory is current
    502655     * directory we assume it is open one)
    503656     */
     
    539692
    540693    /* mark file removed */
    541     rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
    542                                         fat_fd->info_ofs,
     694    rc = msdos_set_first_char4file_name(pathloc->mt_entry, &fat_fd->dir_pos,
    543695                                        MSDOS_THIS_DIR_ENTRY_EMPTY);
    544696    if (rc != RC_OK)
  • cpukit/libfs/src/dosfs/msdos_eval.c

    r8c44190a r07d6fd5  
    8383    rtems_filesystem_location_info_t  newloc;
    8484    int                               i = 0;
    85     int                               len = 0;
     85    int                               token_len = 0;
    8686    msdos_token_types_t               type = MSDOS_CURRENT_DIR;
    87     char                              token[MSDOS_NAME_MAX + 1];
     87    const char                       *token;
    8888
    8989    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
     
    107107    while ((type != MSDOS_NO_MORE_PATH) && (type != MSDOS_INVALID_TOKEN))
    108108    {
    109         type = msdos_get_token(&pathname[i], token, &len);
    110         i += len;
     109        type = msdos_get_token(&pathname[i], &token, &token_len);
     110        i += token_len;
    111111
    112112        fat_fd = pathloc->node_access;
     
    150150
    151151                        rtems_semaphore_release(fs_info->vol_sema);
    152                         return (*pathloc->ops->evalpath_h)(&(pathname[i-len]),
     152                        return (*pathloc->ops->evalpath_h)(&(pathname[i-token_len]),
    153153                                                           flags, pathloc);
    154154                    }
     
    156156                else
    157157                {
    158                     rc = msdos_find_name(pathloc, token);
     158                  rc = msdos_find_name(pathloc, token, token_len);
    159159                    if (rc != RC_OK)
    160160                    {
     
    184184                 * set the node access to the point we have found.
    185185                 */
    186                 rc = msdos_find_name(pathloc, token);
     186                rc = msdos_find_name(pathloc, token, token_len);
    187187                if (rc != RC_OK)
    188188                {
     
    265265    msdos_token_types_t               type;
    266266    int                               i = 0;
    267     int                               len;
    268     char                              token[ MSDOS_NAME_MAX + 1 ];
     267    int                               token_len;
     268    const char                       *token;
    269269    bool                              done = false;
    270270
     
    289289    while (!done)
    290290    {
    291         type = msdos_get_token(&path[i], token, &len);
    292         i += len;
     291        type = msdos_get_token(&path[i], &token, &token_len);
     292        i += token_len;
    293293        fat_fd = pathloc->node_access;
    294294
     
    331331
    332332                        rtems_semaphore_release(fs_info->vol_sema);
    333                         return (*pathloc->ops->evalformake_h)(&path[i-len],
     333                        return (*pathloc->ops->evalformake_h)(&path[i-token_len],
    334334                                                              pathloc, name);
    335335                    }
     
    337337                else
    338338                {
    339                     rc = msdos_find_name(pathloc, token);
     339                    rc = msdos_find_name(pathloc, token, token_len);
    340340                    if (rc != RC_OK)
    341341                    {
     
    362362
    363363                /*
    364                  *  Otherwise find the token name in the present location and
     364                 * Otherwise find the token name in the present location and
    365365                 * set the node access to the point we have found.
    366366                 */
    367                 rc = msdos_find_name(pathloc, token);
     367                rc = msdos_find_name(pathloc, token, token_len);
    368368                if (rc)
    369369                {
     
    397397    }
    398398
    399     *name = &path[i - len];
     399    *name = &path[i - token_len];
    400400
    401401    /*
  • cpukit/libfs/src/dosfs/msdos_file.c

    r8c44190a r07d6fd5  
    224224 *     appropriately).
    225225 */
    226 off_t
    227 msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence)
     226rtems_off64_t
     227msdos_file_lseek(rtems_libio_t *iop, rtems_off64_t offset, int whence)
    228228{
    229229    int                rc = RC_OK;
     
    303303 */
    304304int
    305 msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
     305msdos_file_ftruncate(rtems_libio_t *iop, rtems_off64_t length)
    306306{
    307307    int                rc = RC_OK;
     
    445445}
    446446
     447/* msdos_file_chmod --
     448 *     Change the attributes of the file. This currently does
     449 *     nothing and returns no error.
     450 *
     451 * PARAMETERS:
     452 *     pathloc - node description
     453 *     mode - the new mode
     454 *
     455 * RETURNS:
     456 *     RC_OK always
     457 */
     458int
     459msdos_file_chmod(rtems_filesystem_location_info_t *pathloc,
     460                 mode_t                            mode)
     461{
     462  return RC_OK;
     463}
     464
    447465/* msdos_file_rmnod --
    448466 *     Remove node associated with a file - set up first name character to
     
    470488
    471489    /* mark file removed */
    472     rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
    473                                         fat_fd->info_ofs,
     490    rc = msdos_set_first_char4file_name(pathloc->mt_entry,
     491                                        &fat_fd->dir_pos,
    474492                                        MSDOS_THIS_DIR_ENTRY_EMPTY);
    475493    if (rc != RC_OK)
  • cpukit/libfs/src/dosfs/msdos_format.c

    r8c44190a r07d6fd5  
    3232#include <errno.h>
    3333#include <stdlib.h>
     34#include <stdio.h>
    3435#include <ctype.h>
    3536#include <assert.h>
     
    6667}  msdos_format_param_t;
    6768
     69/*
     70 * Formatted output.
     71 */
     72static void
     73msdos_format_printf (const msdos_format_request_param_t *rqdata,
     74                     int                                 info_level,
     75                     const char                         *format, ...)
     76{
     77  va_list args;
     78  va_start (args, format);
     79  if (rqdata->info_level >= info_level)
     80  {
     81    vfprintf (stdout, format, args);
     82    fflush (stdout);
     83  }
     84}
     85
     86/*=========================================================================*\
     87| Function:                                                                 |
     88\*-------------------------------------------------------------------------*/
     89static int msdos_format_read_sec
     90(
     91/*-------------------------------------------------------------------------*\
     92| Purpose:                                                                  |
     93|     function to read a sector                                             |
     94+---------------------------------------------------------------------------+
     95| Input Parameters:                                                         |
     96\*-------------------------------------------------------------------------*/
     97 int         fd,                       /* file descriptor index            */
     98 uint32_t    start_sector,             /* sector number to write to        */
     99 uint32_t    sector_size,              /* size of sector                   */
     100 char       *buffer                    /* buffer with read data into       */
     101 )
     102/*-------------------------------------------------------------------------*\
     103| Return Value:                                                             |
     104|    0, if success, -1 and errno if failed                                  |
     105\*=========================================================================*/
     106{
     107  int ret_val = 0;
     108
     109  if (0 > lseek(fd,((off_t)start_sector)*sector_size,SEEK_SET)) {
     110    ret_val = -1;
     111  }
     112  if (ret_val == 0) {
     113    if (0 > read(fd,buffer,sector_size)) {
     114      ret_val = -1;
     115    }
     116  }
     117
     118  return ret_val;
     119}
     120
    68121/*=========================================================================*\
    69122| Function:                                                                 |
     
    101154}
    102155
    103 /*=========================================================================*\
     156/*=========================================================================* \
    104157| Function:                                                                 |
    105158\*-------------------------------------------------------------------------*/
     
    112165| Input Parameters:                                                         |
    113166\*-------------------------------------------------------------------------*/
     167 const msdos_format_request_param_t *rqdata,
    114168 int         fd,                       /* file descriptor index            */
    115169 uint32_t    start_sector,             /* sector number to fill to         */
     
    125179  int ret_val = 0;
    126180  char *fill_buffer = NULL;
    127 
     181  uint32_t total_sectors = sector_cnt;
     182  int last_percent = -1;
     183 
    128184  /*
    129185   * allocate and fill buffer
     
    139195    }
    140196  }
     197
     198  msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
     199                       "Filling : ");
    141200  /*
    142201   * write to consecutive sectors
     
    144203  while ((ret_val == 0) &&
    145204         (sector_cnt > 0)) {
     205    int percent = (sector_cnt * 100) / total_sectors;
     206    if (percent != last_percent) {
     207      if ((percent & 1) == 0)
     208        msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL, ".");
     209      last_percent = percent;
     210    }
    146211    ret_val = msdos_format_write_sec(fd,start_sector,sector_size,fill_buffer);
    147212    start_sector++;
    148213    sector_cnt--;
    149214  }
     215 
     216  msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL, "\n");
     217
     218  if (ret_val)
     219    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_INFO,
     220                         "filling error on sector: %d\n", start_sector);
     221 
    150222  /*
    151223   * cleanup
     
    312384  uint32_t onebit;
    313385  uint32_t sectors_per_cluster_adj = 0;
    314 
     386  uint64_t total_size = 0;
     387 
    315388  memset(fmt_params,0,sizeof(*fmt_params));
    316389  /*
     
    321394    fmt_params->bytes_per_sector = dd->block_size;
    322395    fmt_params->totl_sector_cnt  = dd->size;
     396    total_size = dd->block_size * dd->size;
     397    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
     398                         "bytes per sector: %d\ntotal sectors: %d\ntotal size: %lu\n",
     399                         dd->block_size, dd->size, total_size);
    323400  }
    324401  /*
     
    337414    }
    338415  }
     416 
     417  if (ret_val == 0)
     418    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
     419                         "number of fats: %d\n", fmt_params->fat_num);
     420 
    339421  /*
    340422   * Now we get sort of a loop when determining things:
     
    397479       */
    398480      if (fmt_params->totl_sector_cnt
    399           < ((uint32_t)FAT_FAT12_MAX_CLN)*8) {
    400         fmt_params->fattype = FAT_FAT12;
    401         /* start trying with small clusters */
    402         fmt_params->sectors_per_cluster = 2;
     481          < ((uint32_t)FAT_FAT12_MAX_CLN)*8) {
     482        fmt_params->fattype = FAT_FAT12;
     483        /* start trying with small clusters */
     484        fmt_params->sectors_per_cluster = 2;
    403485      }
    404486      else if (fmt_params->totl_sector_cnt
    405                < ((uint32_t)FAT_FAT16_MAX_CLN)*32) {
    406         fmt_params->fattype = FAT_FAT16;
    407         /* start trying with small clusters */
    408         fmt_params->sectors_per_cluster = 2;
     487               < ((uint32_t)FAT_FAT16_MAX_CLN)*32) {
     488        fmt_params->fattype = FAT_FAT16;
     489        /* start trying with small clusters */
     490        fmt_params->sectors_per_cluster = 2;
    409491      }
    410492      else {
    411         fmt_params->fattype = FAT_FAT32;
    412         /* start trying with small clusters... */
    413         fmt_params->sectors_per_cluster = 1;
     493        uint32_t gigs = (total_size + (1024 * 1024 * 1024)) / (1024 * 1024 * 1024);
     494        int b;
     495        fmt_params->fattype = FAT_FAT32;
     496        /* scale with the size of disk... */
     497        for (b = 31; b > 0; b--)
     498          if ((gigs & (1 << b)) != 0)
     499            break;
     500        fmt_params->sectors_per_cluster = 1 << b;
    414501      }
    415502    }
     
    429516     */
    430517    for (onebit = 128;onebit >= 1;onebit = onebit>>1) {
    431       if (fmt_params->sectors_per_cluster > onebit) {
     518      if (fmt_params->sectors_per_cluster >= onebit) {
    432519        fmt_params->sectors_per_cluster = onebit;
    433520        if (fmt_params->sectors_per_cluster
     
    441528
    442529  if (ret_val == 0) {
     530    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
     531                         "sectors per cluster: %d\n", fmt_params->sectors_per_cluster);
     532   
    443533    if (fmt_params->fattype == FAT_FAT32) {
    444534      /* recommended: for FAT32, always set reserved sector count to 32 */
     
    650740  }
    651741  /*
    652    * finally we are there: let's fill in the values into the MBR
    653    */
    654   memset(mbr,0,FAT_TOTAL_MBR_SIZE);
     742   * finally we are there: let's fill in the values into the MBR
     743   * but first clear the MRB leaving the partition table.
     744   */
     745#define RTEMS_IDE_PARTITION_TABLE_OFFSET                  0x1be
     746#define RTEMS_IDE_PARTITION_TABLE_SIZE                    (4 * 16)
     747  memset(mbr,0,RTEMS_IDE_PARTITION_TABLE_OFFSET);
     748  memset(mbr + RTEMS_IDE_PARTITION_TABLE_OFFSET + RTEMS_IDE_PARTITION_TABLE_SIZE,
     749         0,
     750         FAT_TOTAL_MBR_SIZE - (RTEMS_IDE_PARTITION_TABLE_OFFSET + RTEMS_IDE_PARTITION_TABLE_SIZE));
    655751  /*
    656752   * FIXME: fill jmpBoot and Boot code...
     
    673769  FAT_SET_BR_MEDIA(mbr               , fmt_params->media_code);
    674770
    675   FAT_SET_BR_SECTORS_PER_TRACK(mbr   , 0); /* only needed for INT13... */
    676   FAT_SET_BR_NUMBER_OF_HEADS(mbr     , 0); /* only needed for INT13... */
    677   FAT_SET_BR_HIDDEN_SECTORS(mbr      , 0); /* only needed for INT13... */
     771  FAT_SET_BR_SECTORS_PER_TRACK(mbr   , 255); /* only needed for INT13... */
     772  FAT_SET_BR_NUMBER_OF_HEADS(mbr     , 6);  /* only needed for INT13... */
     773  FAT_SET_BR_HIDDEN_SECTORS(mbr      , 1);  /* only needed for INT13... */
    678774
    679775  FAT_SET_BR_TOTAL_SECTORS_NUM32(mbr , total_sectors_num32);
     
    750846\*=========================================================================*/
    751847{
    752 
    753848  /*
    754849   * clear fsinfo sector data
     
    761856  FAT_SET_FSINFO_STRUC_SIGNATURE(fsinfo,FAT_FSINFO_STRUC_SIGNATURE_VALUE);
    762857  FAT_SET_FSINFO_TRAIL_SIGNATURE(fsinfo,FAT_FSINFO_TRAIL_SIGNATURE_VALUE);
    763 /*
    764  * write "empty" values for free cluster count and next cluster number
    765  */
     858  /*
     859   * write "empty" values for free cluster count and next cluster number
     860   */
    766861  FAT_SET_FSINFO_FREE_CLUSTER_COUNT(fsinfo+FAT_FSI_INFO,
    767862                                    0xffffffff);
     
    801896  msdos_format_param_t fmt_params;
    802897
     898  msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_INFO,
     899                       "formating: %s\n", devname);
    803900  /*
    804901   * sanity check on device
    805902   */
     903  msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
     904                       "stat check: %s\n", devname);
    806905  if (ret_val == 0) {
    807906    rc = stat(devname, &stat_buf);
     
    829928   */
    830929  if (ret_val == 0) {
    831     fd = open(devname, O_WRONLY);
     930    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
     931                         "open device\n");
     932    fd = open(devname, O_RDWR);
    832933    if (fd == -1)
    833934    {
     
    849950      !(rqdata->quick_format)) {
    850951    ret_val = msdos_format_fill_sectors
    851       (fd,
     952      (rqdata,
     953       fd,
    852954       0,                            /* start sector */
    853955       fmt_params.totl_sector_cnt,   /* sector count */
     
    859961   */
    860962  if (ret_val == 0) {
    861     ret_val = msdos_format_gen_mbr(tmp_sec,&fmt_params);
    862   }
    863   /*
    864    * write master boot record to disk
    865    * also write copy of MBR to disk
    866    */
    867   if (ret_val == 0) {
    868     ret_val = msdos_format_write_sec(fd,
    869                                      0,
    870                                      fmt_params.bytes_per_sector,
    871                                      tmp_sec);
    872   }
    873   if ((ret_val == 0) &&
    874       (fmt_params.mbr_copy_sec != 0)) {
    875963    /*
    876      * write copy of MBR
     964     * Read the current MBR to obtain the partition table.
    877965     */
    878     ret_val = msdos_format_write_sec(fd,
    879                                      fmt_params.mbr_copy_sec ,
    880                                      fmt_params.bytes_per_sector,
    881                                      tmp_sec);
     966    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
     967                         "read MRB sector\n");
     968    ret_val = msdos_format_read_sec(fd,
     969                                    0,
     970                                    fmt_params.bytes_per_sector,
     971                                    tmp_sec);
     972    if (ret_val == 0) {
     973      msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
     974                           "generate MRB sector\n");
     975      ret_val = msdos_format_gen_mbr(tmp_sec,&fmt_params);
     976    }
     977   
     978    /*
     979     * write master boot record to disk
     980     * also write copy of MBR to disk
     981     */
     982    if (ret_val == 0) {
     983      msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
     984                           "write MRB sector\n");
     985      ret_val = msdos_format_write_sec(fd,
     986                                       0,
     987                                       fmt_params.bytes_per_sector,
     988                                       tmp_sec);
     989    }
     990    if ((ret_val == 0) &&
     991        (fmt_params.mbr_copy_sec != 0)) {
     992      /*
     993       * write copy of MBR
     994       */
     995      msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
     996                           "write back up MRB sector\n");
     997      ret_val = msdos_format_write_sec(fd,
     998                                       fmt_params.mbr_copy_sec ,
     999                                       fmt_params.bytes_per_sector,
     1000                                       tmp_sec);
     1001    }
    8821002  }
    8831003  /*
     
    9041024  if (ret_val == 0) {
    9051025    ret_val = msdos_format_fill_sectors
    906       (fd,
     1026      (rqdata,
     1027       fd,
    9071028       fmt_params.rsvd_sector_cnt,                   /* start sector */
    9081029       fmt_params.fat_num*fmt_params.sectors_per_fat,/* sector count */
     
    9161037  if (ret_val == 0) {
    9171038    ret_val = msdos_format_fill_sectors
    918       (fd,
     1039      (rqdata,
     1040       fd,
    9191041       fmt_params.root_dir_start_sec,        /* start sector */
    9201042       fmt_params.root_dir_fmt_sec_cnt,      /* sector count */
  • cpukit/libfs/src/dosfs/msdos_handlers_dir.c

    r8c44190a r07d6fd5  
    2727    msdos_dir_lseek,
    2828    msdos_dir_stat,
    29     NULL,
     29    msdos_dir_chmod,
    3030    NULL,             /* msdos_dir_ftruncate */
    3131    NULL,
  • cpukit/libfs/src/dosfs/msdos_handlers_file.c

    r8c44190a r07d6fd5  
    2727    msdos_file_lseek,
    2828    msdos_file_stat,
    29     NULL,
     29    msdos_file_chmod,
    3030    msdos_file_ftruncate,
    3131    NULL,
  • cpukit/libfs/src/dosfs/msdos_init.c

    r8c44190a r07d6fd5  
    4343
    4444/* msdos_initialize --
    45  *     MSDOS filesystem initialization
     45 *     MSDOS filesystem initialization. Called when mounting an
     46 *     MSDOS filesystem.
    4647 *
    4748 * PARAMETERS:
  • cpukit/libfs/src/dosfs/msdos_initsupp.c

    r8c44190a r07d6fd5  
    5858    msdos_fs_info_t   *fs_info = NULL;
    5959    fat_file_fd_t     *fat_fd = NULL;
     60    fat_dir_pos_t      root_pos;
    6061    uint32_t           cl_buf_size;
    6162
     
    8081     * (so inode number 0x00000010 is always used for root directory)
    8182     */
    82     rc = fat_file_open(temp_mt_entry, FAT_ROOTDIR_CLUSTER_NUM, 0, &fat_fd);
     83    fat_dir_pos_init(&root_pos);
     84    root_pos.sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
     85    rc = fat_file_open(temp_mt_entry, &root_pos, &fat_fd);
    8386    if (rc != RC_OK)
    8487    {
     
    9194    fat_fd->fat_file_type = FAT_DIRECTORY;
    9295    fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
    93     fat_fd->info_cln = FAT_ROOTDIR_CLUSTER_NUM;
    94     fat_fd->info_ofs = 0;
    9596    fat_fd->cln = fs_info->fat.vol.rdir_cl;
    9697
  • cpukit/libfs/src/dosfs/msdos_misc.c

    r8c44190a r07d6fd5  
    1919
    2020#include <stdlib.h>
     21#include <ctype.h>
    2122#include <sys/time.h>
    2223#include <unistd.h>
     
    3132#include "msdos.h"
    3233
     34
     35#include <stdio.h>
     36
     37/*
     38 * External strings. Saves spave this way.
     39 */
     40const char const* MSDOS_DOT_NAME    = ".          ";
     41const char const* MSDOS_DOTDOT_NAME = "..         ";
     42
     43/* msdos_is_valid_name_char --
     44 *     Routine to check the character in a file or directory name.
     45 *     The characters support in the short file name are letters,
     46 *     digits, or characters with code points values greater than
     47 *     127 (not sure what this last is) plus the following special
     48 *     characters "$%'-_@~`!(){}^#&". The must be uppercase.
     49 *
     50 *     The following 6 characters are allowed in a long names,
     51 *     " +,;=[]" including a space and lower case letters.
     52 *
     53 * PARAMETERS:
     54 *     ch        - character to check.
     55 *
     56 * RETURNS:
     57 *     MSDOS_NAME_INVALID - Not valid in a long or short name.
     58 *     MSDOS_NAME_SHORT   - Valid in a short name or long name.
     59 *     MSDOS_NAME_LONG    - Valid in a long name only.
     60 *
     61 */
     62static msdos_name_type_t
     63msdos_is_valid_name_char(const char ch)
     64{
     65    if (strchr(" +,;=[]", ch) != NULL)
     66        return MSDOS_NAME_LONG;
     67
     68    if ((ch == '.') || isalnum(ch) ||
     69        (strchr("$%'-_@~`!(){}^#&", ch) != NULL))
     70        return MSDOS_NAME_SHORT;
     71   
     72    return MSDOS_NAME_INVALID;
     73}
     74
     75/* msdos_short_hex_number --
     76 *     Routine to set the hex number in the SFN.
     77 *
     78 * PARAMETERS:
     79 *     name      - name to change
     80 *     num       - number to set
     81 *
     82 * RETURNS:
     83 *     nothing
     84 *
     85 */
     86static void
     87msdos_short_name_hex(char* sfn, int num)
     88{
     89    static const char* hex = "0123456789ABCDEF";
     90    char* c = MSDOS_DIR_NAME(sfn);
     91    int   i;
     92    for (i = 0; i < 3; i++, c++)
     93      if ((*c == ' ') || (*c == '.'))
     94        *c = '~';
     95    *c++ = '~';
     96    for (i = 0; i < 4; i++, c++)
     97      *c = hex[(num >> ((3 - i) * 4)) & 0xf];
     98}
     99
     100/* msdos_name_type --
     101 *     Routine the type of file name.
     102 *
     103 * PARAMETERS:
     104 *     name      - name to check
     105 *
     106 * RETURNS:
     107 *     true the name is long, else the name is short.
     108 *
     109 */
     110static msdos_name_type_t
     111msdos_name_type(const char *name, int name_len)
     112{
     113    bool dot = false;
     114    bool lowercase = false;
     115    bool uppercase = false;
     116    int  dot_at = 0;
     117    int  count = 0;
     118
     119    while (*name && (count < name_len))
     120    {
     121        msdos_name_type_t type = msdos_is_valid_name_char(*name);
     122
     123        if ((type == MSDOS_NAME_INVALID) || (type == MSDOS_NAME_LONG))
     124            return type;
     125
     126        if (dot)
     127        {
     128            if ((*name == '.') || ((count - dot_at) > 3))
     129                return MSDOS_NAME_LONG;
     130        }
     131        else
     132        {
     133            if (count >= 8)
     134                return MSDOS_NAME_LONG;
     135        }
     136
     137        if (*name == '.')
     138        {
     139            dot = true;
     140            dot_at = count;
     141        }
     142        else if ((*name >= 'A') && (*name <= 'Z'))
     143            uppercase = true;
     144        else if ((*name >= 'a') && (*name <= 'z'))
     145            lowercase = true;
     146       
     147        count++;
     148        name++;
     149    }
     150
     151    if (lowercase && uppercase)
     152        return MSDOS_NAME_LONG;
     153   
     154    return MSDOS_NAME_SHORT;
     155}
     156
     157/* msdos_long_to_short --
     158 *     Routine to creates a short name from a long. Start the end of the
     159 *
     160 * PARAMETERS:
     161 *     name      - name to check
     162 *
     163 * RETURNS:
     164 *     true the name is long, else the name is short.
     165 *
     166 */
     167msdos_name_type_t
     168msdos_long_to_short(const char *lfn, int lfn_len, char* sfn, int sfn_len)
     169{
     170    msdos_name_type_t type;
     171    int               i;
     172
     173    /*
     174     * Fill with spaces. This is how a short directory entry is padded.
     175     */
     176    memset (sfn, ' ', sfn_len);
     177
     178    /*
     179     * Handle '.' and '..' specially.
     180     */
     181    if ((lfn[0] == '.') && (lfn_len == 1))
     182    {
     183        sfn[0] = '.';
     184        return MSDOS_NAME_SHORT;
     185    }
     186       
     187    if ((lfn[0] == '.') && (lfn[1] == '.') && (lfn_len == 2))
     188    {
     189        sfn[0] = sfn[1] = '.';
     190        return MSDOS_NAME_SHORT;
     191    }
     192
     193    /*
     194     * Filenames with only blanks and dots are not allowed!
     195     */
     196    for (i = 0; i < lfn_len; i++)
     197        if ((lfn[i] != ' ') && (lfn[i] == '.'))
     198            break;
     199
     200    if (i > lfn_len)
     201        return MSDOS_NAME_INVALID;
     202
     203    /*
     204     * Is this a short name ?
     205     */
     206   
     207    type = msdos_name_type (lfn, lfn_len);
     208
     209    if (type == MSDOS_NAME_INVALID)
     210        return MSDOS_NAME_INVALID;
     211   
     212    msdos_filename_unix2dos (lfn, lfn_len, sfn);
     213   
     214    return type;
     215}
     216
    33217/* msdos_get_token --
    34218 *     Routine to get a token (name or separator) from the path.
     
    44228 */
    45229msdos_token_types_t
    46 msdos_get_token(const char *path, char *ret_token, int *token_len)
     230msdos_get_token(const char *path, const char **ret_token, int *ret_token_len)
    47231{
    48     int                 rc = RC_OK;
    49     register int        i = 0;
    50232    msdos_token_types_t type = MSDOS_NAME;
    51     char                token[MSDOS_NAME_MAX_WITH_DOT+1];
    52     register char       c;
    53 
    54     /*
    55      *  Copy a name into token.  (Remember NULL is a token.)
    56      */
    57     c = path[i];
    58     while ( (!msdos_is_separator(c)) && (i <= MSDOS_NAME_MAX_WITH_DOT) )
    59     {
    60         token[i] = c;
    61         if ( i == MSDOS_NAME_MAX_WITH_DOT )
     233    int                 i = 0;
     234
     235    *ret_token = NULL;
     236    *ret_token_len = 0;
     237
     238    /*
     239     *  Check for a separator.
     240     */
     241    while (!msdos_is_separator(path[i]))
     242    {
     243        if ( !msdos_is_valid_name_char(path[i]) )
    62244            return MSDOS_INVALID_TOKEN;
    63         if ( !msdos_is_valid_name_char(c) )
     245        ++i;
     246        if ( i == MSDOS_NAME_MAX_LFN_WITH_DOT )
    64247            return MSDOS_INVALID_TOKEN;
    65         c = path [++i];
    66     }
    67 
    68     /*
    69      *  Copy a seperator into token.
     248    }
     249
     250    *ret_token = path;
     251   
     252    /*
     253     *  If it is just a separator then it is the current dir.
    70254     */
    71255    if ( i == 0 )
    72256    {
    73         token[i] = c;
    74         if ( token[i] != '\0' )
     257        if ( *path != '\0' )
    75258        {
    76259            i++;
     
    80263            type = MSDOS_NO_MORE_PATH;
    81264    }
    82     else if (token[ i-1 ] != '\0')
    83         token[i] = '\0';
    84 
    85     /*
    86      *  Set token_len to the number of characters copied.
    87      */
    88     *token_len = i;
     265
     266    /*
     267     *  Set the token and token_len to the token start and length.
     268     */
     269    *ret_token_len = i;
    89270
    90271    /*
     
    94275    if ( type == MSDOS_NAME )
    95276    {
    96         if ( strcmp( token, "..") == 0 )
     277        if ((i == 2) && ((*ret_token)[0] == '.') && ((*ret_token)[1] == '.'))
    97278        {
    98             strcpy(ret_token, MSDOS_DOTDOT_NAME);
    99279            type = MSDOS_UP_DIR;
    100280            return type;
    101281        }
    102282
    103         if ( strcmp( token, "." ) == 0 )
     283        if ((i == 1) && ((*ret_token)[0] == '.'))
    104284        {
    105             strcpy(ret_token, MSDOS_DOT_NAME);
    106285            type = MSDOS_CURRENT_DIR;
    107286            return type;
    108287        }
    109 
    110         rc = msdos_filename_unix2dos(token, *token_len, ret_token);
    111         if ( rc != RC_OK )
    112             return MSDOS_INVALID_TOKEN;
    113     }
    114     ret_token[MSDOS_NAME_MAX] = '\0';
     288    }
     289
    115290    return type;
    116291}
     
    134309msdos_find_name(
    135310    rtems_filesystem_location_info_t *parent_loc,
    136     char                             *name
     311    const char                       *name,
     312    int                               name_len
    137313    )
    138314{
    139     int              rc = RC_OK;
    140     msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
    141     fat_file_fd_t   *fat_fd = NULL;
    142     fat_auxiliary_t  aux;
    143     unsigned short   time_val = 0;
    144     unsigned short   date = 0;
    145     char             node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
     315    int                rc = RC_OK;
     316    msdos_fs_info_t   *fs_info = parent_loc->mt_entry->fs_info;
     317    fat_file_fd_t     *fat_fd = NULL;
     318    msdos_name_type_t  name_type;
     319    fat_dir_pos_t      dir_pos;
     320    unsigned short     time_val = 0;
     321    unsigned short     date = 0;
     322    char               node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
    146323
    147324    memset(node_entry, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
     325
     326    name_type = msdos_long_to_short (name,
     327                                     name_len,
     328                                     MSDOS_DIR_NAME(node_entry),
     329                                     MSDOS_NAME_MAX);
    148330
    149331    /*
     
    151333     * 'parent_loc'
    152334     */
    153     rc = msdos_get_name_node(parent_loc, name, &aux, node_entry);
     335    rc = msdos_get_name_node(parent_loc, false, name, name_len, name_type,
     336                             &dir_pos, node_entry);
    154337    if (rc != RC_OK)
    155338        return rc;
    156339
     340    if (((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_VOLUME_ID) ||
     341        ((*MSDOS_DIR_ATTR(node_entry) & MSDOS_ATTR_LFN_MASK) == MSDOS_ATTR_LFN))
     342        return MSDOS_NAME_NOT_FOUND_ERR;
     343
    157344    /* open fat-file corresponded to the found node */
    158     rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
     345    rc = fat_file_open(parent_loc->mt_entry, &dir_pos, &fat_fd);
    159346    if (rc != RC_OK)
    160347        return rc;
    161348
    162     /*
    163      * I don't like this if, but: we should do it , or should write new file
     349    fat_fd->dir_pos = dir_pos;
     350   
     351    /*
     352     * I don't like this if, but: we should do it, or should write new file
    164353     * size and first cluster num to the disk after each write operation
    165      * (even if one byte is written  - that is TOO non-optimize) because
     354     * (even if one byte is written  - that is TOO slow) because
    166355     * otherwise real values of these fields stored in fat-file descriptor
    167      * may be accidentely rewritten with wrong values stored on the disk
     356     * may be accidentally rewritten with wrong values stored on the disk
    168357     */
    169358    if (fat_fd->links_num == 1)
    170359    {
    171         fat_fd->info_cln = aux.cln;
    172         fat_fd->info_ofs = aux.ofs;
    173360        fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(node_entry);
    174         fat_fd->first_char = *MSDOS_DIR_NAME(node_entry);
    175361
    176362        time_val = *MSDOS_DIR_WRITE_TIME(node_entry);
    177363        date = *MSDOS_DIR_WRITE_DATE(node_entry);
    178364
    179         fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(time_val), CF_LE_W(date));
     365        fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(date), CF_LE_W(time_val));
    180366
    181367        if ((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_DIRECTORY)
     
    228414
    229415/* msdos_get_name_node --
    230  *     This routine is used in two ways: for a new mode creation (a) or for
     416 *     This routine is used in two ways: for a new node creation (a) or for
    231417 *     search the node which correspondes to the name parameter (b).
    232418 *     In case (a) 'name' should be set up to NULL and 'name_dir_entry' should
     
    248434 *     paux           - identify a node location on the disk -
    249435 *                      cluster num and offset inside the cluster
    250  *     name_dir_entry - node to create/placeholder for found node (IN/OUT)
     436 *     short_dir_entry - node to create/placeholder for found node (IN/OUT)
    251437 *
    252438 * RETURNS:
     
    258444msdos_get_name_node(
    259445    rtems_filesystem_location_info_t *parent_loc,
    260     char                             *name,
    261     fat_auxiliary_t                  *paux,
     446    bool                              create_node,
     447    const char                       *name,
     448    int                               name_len,
     449    msdos_name_type_t                 name_type,
     450    fat_dir_pos_t                    *dir_pos,
    262451    char                             *name_dir_entry
    263452    )
    264453{
    265454    int              rc = RC_OK;
    266     ssize_t          ret = 0;
    267     msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
    268455    fat_file_fd_t   *fat_fd = parent_loc->node_access;
    269456    uint32_t         dotdot_cln = 0;
    270457
    271     /* find name in fat-file which correspondes to the directory */
    272     rc = msdos_find_name_in_fat_file(parent_loc->mt_entry, fat_fd, name, paux,
    273                                      name_dir_entry);
     458    /* find name in fat-file which corresponds to the directory */
     459    rc = msdos_find_name_in_fat_file(parent_loc->mt_entry, fat_fd,
     460                                     create_node, name, name_len, name_type,
     461                                     dir_pos, name_dir_entry);
    274462    if ((rc != RC_OK) && (rc != MSDOS_NAME_NOT_FOUND_ERR))
    275463        return rc;
    276464
    277     /* if we search for valid name and name not found -> return */
    278     if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name != NULL))
    279         return rc;
    280 
    281     /*
    282      * if we try to create new entry and the directory is not big enough
    283      * currently - try to enlarge directory
    284      */
    285     if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name == NULL))
    286     {
    287         ret = fat_file_write(parent_loc->mt_entry, fat_fd,
    288                              fat_fd->fat_file_size,
    289                              MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
    290                              (uint8_t *)name_dir_entry);
    291         if (ret == -1)
    292             return -1;
    293 
    294         /* on success directory is enlarged by a new cluster */
    295         fat_fd->fat_file_size += fs_info->fat.vol.bpc;
    296 
    297         /* get cluster num where a new node located */
    298         rc = fat_file_ioctl(parent_loc->mt_entry, fat_fd, F_CLU_NUM,
    299                             fat_fd->fat_file_size - 1, &paux->cln);
    300 
    301         if (rc != RC_OK)
     465    if (!create_node)
     466    {
     467        /* if we search for valid name and name not found -> return */
     468        if (rc == MSDOS_NAME_NOT_FOUND_ERR)
    302469            return rc;
    303470
    304471        /*
    305          * if new cluster allocated succesfully then new node is at very
    306          * beginning of the cluster (offset is computed in bytes)
     472         * if we have deal with ".." - it is a special case :(((
     473         *
     474         * Really, we should return cluster num and offset not of ".." slot, but
     475         * slot which correspondes to real directory name.
    307476         */
    308         paux->ofs = 0;
    309         return RC_OK;
    310     }
    311 
    312     /*
    313      * if we have deal with ".." - it is a special case :(((
    314      *
    315      * Really, we should return cluster num and offset not of ".." slot, but
    316      * slot which correspondes to real directory name.
    317      */
    318     if ((rc == RC_OK) && (name != NULL))
    319     {
    320         if (strncmp(name, MSDOS_DOTDOT_NAME, MSDOS_SHORT_NAME_LEN) == 0)
     477        if (rc == RC_OK)
    321478        {
    322             dotdot_cln = MSDOS_EXTRACT_CLUSTER_NUM((name_dir_entry));
    323 
    324             /* are we right under root dir ? */
    325             if (dotdot_cln == 0)
     479            if (strncmp(name, "..", 2) == 0)
    326480            {
    327                 /*
    328                  * we can relax about first_char field - it never should be
    329                  * used for root dir
    330                  */
    331                 paux->cln = FAT_ROOTDIR_CLUSTER_NUM;
    332                 paux->ofs = 0;
    333             }
    334             else
    335             {
    336                 rc = msdos_get_dotdot_dir_info_cluster_num_and_offset(
    337                         parent_loc->mt_entry,
    338                         dotdot_cln,
    339                         paux,
    340                         name_dir_entry
    341                         );
    342                 if (rc != RC_OK)
    343                     return rc;
     481                dotdot_cln = MSDOS_EXTRACT_CLUSTER_NUM((name_dir_entry));
     482
     483                /* are we right under root dir ? */
     484                if (dotdot_cln == 0)
     485                {
     486                    /*
     487                     * we can relax about first_char field - it never should be
     488                     * used for root dir
     489                     */
     490                    fat_dir_pos_init(dir_pos);
     491                    dir_pos->sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
     492                }
     493                else
     494                {
     495                    rc =
     496                        msdos_get_dotdot_dir_info_cluster_num_and_offset(parent_loc->mt_entry,
     497                                                                         dotdot_cln,
     498                                                                         dir_pos,
     499                                                                         name_dir_entry);
     500                    if (rc != RC_OK)
     501                        return rc;
     502                }
    344503            }
    345504        }
     
    381540    rtems_filesystem_mount_table_entry_t *mt_entry,
    382541    uint32_t                              cln,
    383     fat_auxiliary_t                      *paux,
     542    fat_dir_pos_t                        *dir_pos,
    384543    char                                 *dir_entry
    385544    )
     
    392551    uint32_t         cl4find = 0;
    393552
    394     memset(dot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
    395     memset(dotdot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
    396 
    397553    /*
    398554     * open fat-file corresponded to ".."
    399555     */
    400     rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd);
     556    rc = fat_file_open(mt_entry, dir_pos, &fat_fd);
    401557    if (rc != RC_OK)
    402558        return rc;
    403559
    404     fat_fd->info_cln = paux->cln;
    405     fat_fd->info_ofs = paux->ofs;
    406560    fat_fd->cln = cln;
    407561    fat_fd->fat_file_type = FAT_DIRECTORY;
     
    419573
    420574    /* find "." node in opened directory */
    421     rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOT_NAME, paux,
    422                                      dot_node);
     575    memset(dot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
     576    msdos_long_to_short(".", 1, dot_node, MSDOS_SHORT_NAME_LEN);
     577    rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, false, ".", 1,
     578                                     MSDOS_NAME_SHORT, dir_pos, dot_node);
    423579
    424580    if (rc != RC_OK)
     
    429585
    430586    /* find ".." node in opened directory */
    431     rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOTDOT_NAME, paux,
     587    memset(dotdot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
     588    msdos_long_to_short("..", 2, dotdot_node, MSDOS_SHORT_NAME_LEN);
     589    rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, false, "..", 2,
     590                                     MSDOS_NAME_SHORT, dir_pos,
    432591                                     dotdot_node);
    433592
     
    451610         * ordinary directories ( through fat_file_* calls )
    452611         */
    453         paux->cln = FAT_ROOTDIR_CLUSTER_NUM;
    454         paux->ofs = 0;
     612        fat_dir_pos_init(dir_pos);
     613        dir_pos->sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
    455614    }
    456615
    457616    /* open fat-file corresponded to second ".." */
    458     rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd);
     617    rc = fat_file_open(mt_entry, dir_pos, &fat_fd);
    459618    if (rc != RC_OK)
    460619        return rc;
    461 
    462     fat_fd->info_cln = paux->cln;
    463     fat_fd->info_ofs = paux->ofs;
    464620
    465621    if ((MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0)
     
    483639    /* in this directory find slot with specified cluster num */
    484640    rc = msdos_find_node_by_cluster_num_in_fat_file(mt_entry, fat_fd, cl4find,
    485                                                     paux, dir_entry);
     641                                                    dir_pos, dir_entry);
    486642    if (rc != RC_OK)
    487643    {
     
    519675    uint32_t         byte = 0;
    520676
    521     msdos_date_unix2dos(fat_fd->mtime, &time_val, &date);
     677    msdos_date_unix2dos(fat_fd->mtime, &date, &time_val);
    522678
    523679    /*
     
    525681     * (sector num, new offset)
    526682     */
    527     sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln);
    528     sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2);
     683    sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->dir_pos.sname.cln);
     684    sec += (fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
    529685    /* byte points to start of 32bytes structure */
    530     byte = fat_fd->info_ofs & (fs_info->fat.vol.bps - 1);
     686    byte = fat_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1);
    531687
    532688    time_val = CT_LE_W(time_val);
     
    573729     * (sector num, new offset)
    574730     */
    575     sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln);
    576     sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2);
     731    sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->dir_pos.sname.cln);
     732    sec += (fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
    577733    /* byte from points to start of 32bytes structure */
    578     byte = fat_fd->info_ofs & (fs_info->fat.vol.bps - 1);
     734    byte = fat_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1);
    579735
    580736    le_cl_low = CT_LE_W((uint16_t  )(new_cln & 0x0000FFFF));
     
    616772    uint32_t         byte = 0;
    617773
    618     sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln);
    619     sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2);
    620     byte = (fat_fd->info_ofs & (fs_info->fat.vol.bps - 1));
     774    sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->dir_pos.sname.cln);
     775    sec += (fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
     776    byte = (fat_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1));
    621777
    622778    le_new_length = CT_LE_L((fat_fd->fat_file_size));
     
    651807msdos_set_first_char4file_name(
    652808    rtems_filesystem_mount_table_entry_t *mt_entry,
    653     uint32_t                              cl,
    654     uint32_t                              ofs,
     809    fat_dir_pos_t                        *dir_pos,
    655810    unsigned char                         fchar
    656811    )
    657812{
    658     ssize_t          ret = 0;
     813    ssize_t          ret;
    659814    msdos_fs_info_t *fs_info = mt_entry->fs_info;
    660     uint32_t         sec = 0;
    661     uint32_t         byte = 0;
    662 
    663     sec = fat_cluster_num_to_sector_num(mt_entry, cl);
    664     sec += (ofs >> fs_info->fat.vol.sec_log2);
    665     byte = (ofs & (fs_info->fat.vol.bps - 1));
    666 
    667     ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_NAME_OFFSET, 1,
    668                            &fchar);
    669     if ( ret < 0)
     815    uint32_t         dir_block_size;
     816    fat_pos_t        start = dir_pos->lname;
     817    fat_pos_t        end = dir_pos->sname;
     818
     819    if ((end.cln == fs_info->fat.vol.rdir_cl) &&
     820        (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
     821      dir_block_size = fs_info->fat.vol.rdir_size;
     822    else
     823      dir_block_size = fs_info->fat.vol.bpc;
     824   
     825    if (dir_pos->lname.cln == FAT_FILE_SHORT_NAME)
     826      start = dir_pos->sname;
     827
     828    /*
     829     * We handle the changes directly due the way the short file
     830     * name code was written rather than use the fat_file_write
     831     * interface.
     832     */
     833    while (true)
     834    {
     835      uint32_t sec = (fat_cluster_num_to_sector_num(mt_entry, start.cln) +
     836                      (start.ofs >> fs_info->fat.vol.sec_log2));
     837      uint32_t byte = (start.ofs & (fs_info->fat.vol.bps - 1));;
     838
     839      ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_NAME_OFFSET, 1,
     840                             &fchar);
     841      if (ret < 0)
    670842        return -1;
     843
     844      if ((start.cln == end.cln) && (start.ofs == end.ofs))
     845        break;
     846
     847      start.ofs += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
     848      if (start.ofs >= dir_block_size)
     849      {
     850        int rc;
     851        if ((end.cln == fs_info->fat.vol.rdir_cl) &&
     852            (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
     853          break;
     854        rc = fat_get_fat_cluster(mt_entry, start.cln, &start.cln);
     855        if ( rc != RC_OK )
     856          return rc;
     857        start.ofs = 0;
     858      }
     859    }
    671860
    672861    return  RC_OK;
     
    714903             i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
    715904        {
    716             if (((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
     905            char* entry = (char*) fs_info->cl_buf + i;
     906
     907            /*
     908             * If the entry is empty, a long file name entry, or '.' or '..'
     909             * then consider it as empty.
     910             *
     911             * Just ignore long file name entries. They must have a short entry to
     912             * be valid.
     913             */
     914            if (((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
    717915                 MSDOS_THIS_DIR_ENTRY_EMPTY) ||
    718                 (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), MSDOS_DOT_NAME,
     916                ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) ==
     917                 MSDOS_ATTR_LFN) ||
     918                (strncmp(MSDOS_DIR_NAME((entry)), MSDOS_DOT_NAME,
    719919                         MSDOS_SHORT_NAME_LEN) == 0) ||
    720                 (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)),
     920                (strncmp(MSDOS_DIR_NAME((entry)),
    721921                         MSDOS_DOTDOT_NAME,
    722922                         MSDOS_SHORT_NAME_LEN) == 0))
    723923                continue;
    724924
    725             if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
     925            /*
     926             * Nothing more to look at.
     927             */
     928            if ((*MSDOS_DIR_NAME(entry)) ==
    726929                MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
    727930            {
     
    729932                return RC_OK;
    730933            }
     934
     935            /*
     936             * Short file name entries mean not empty.
     937             */
    731938            return RC_OK;
    732939        }
     
    737944}
    738945
    739 
    740 /* msdos_find_name_in_fat_file --
    741  *     This routine is used in two ways: for a new mode creation (a) or for
    742  *     search the node which correspondes to the 'name' parameter (b).
    743  *     In case (a) name should be set up to NULL and 'name_dir_entry' should
    744  *     point to initialized 32 bytes structure described a new node.
    745  *     In case (b) 'name' should contain a valid string.
    746  *
    747  *     (a): reading fat-file corresponded to directory we are going to create
    748  *          node in. If found free slot write contents of name_dir_entry into
    749  *          it.
    750  *
    751  *     (b): reading fat-file corresponded to directory and trying to find slot
    752  *          with the name field == name parameter
     946/* msdos_create_name_in_fat_file --
     947 *     This routine creates an entry in the fat file for the file name
     948 *     provided by the user. The directory entry passed is the short
     949 *     file name and is added as it. If the file name is long a long
     950 *     file name set of entries is added.
     951 *
     952 *     Scan the directory for the file and if not found add the new entry.
     953 *     When scanning remember the offset in the file where the directory
     954 *     entry can be added.
    753955 *
    754956 * PARAMETERS:
     
    765967 *
    766968 */
     969#define MSDOS_FIND_PRINT 0
    767970int msdos_find_name_in_fat_file(
    768971    rtems_filesystem_mount_table_entry_t *mt_entry,
    769972    fat_file_fd_t                        *fat_fd,
    770     char                                 *name,
    771     fat_auxiliary_t                      *paux,
     973    bool                                  create_node,
     974    const char                           *name,
     975    int                                   name_len,
     976    msdos_name_type_t                     name_type,
     977    fat_dir_pos_t                        *dir_pos,
    772978    char                                 *name_dir_entry
    773     )
     979                                )
    774980{
    775     int              rc = RC_OK;
    776981    ssize_t          ret = 0;
    777982    msdos_fs_info_t *fs_info = mt_entry->fs_info;
    778     uint32_t         i = 0, j = 0;
     983    uint32_t         dir_offset = 0;
     984    uint32_t         dir_entry = 0;
    779985    uint32_t         bts2rd = 0;
    780 
     986    fat_pos_t        lfn_start;
     987    bool             lfn_matched = false;
     988    uint8_t          lfn_checksum = 0;
     989    int              lfn_entries = 0;
     990    int              lfn_entry = 0;
     991    uint32_t         empty_space_offset = 0;
     992    uint32_t         empty_space_entry = 0;
     993    uint32_t         empty_space_count = 0;
     994    bool             empty_space_found = false;
     995    uint32_t         entries_per_block;
     996    bool             read_cluster = false;
     997
     998    assert(name_len > 0);
     999
     1000    fat_dir_pos_init(dir_pos);
     1001   
     1002    lfn_start.cln = lfn_start.ofs = FAT_FILE_SHORT_NAME;
     1003   
     1004    /*
     1005     * If the file name is long how many short directory
     1006     * entries are needed ?
     1007     */
     1008    if (name_type == MSDOS_NAME_LONG)
     1009        lfn_entries = ((name_len - 1) + MSDOS_LFN_LEN_PER_ENTRY) / MSDOS_LFN_LEN_PER_ENTRY;
     1010           
    7811011    if (FAT_FD_OF_ROOT_DIR(fat_fd) &&
    782        (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
     1012        (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
    7831013        bts2rd = fat_fd->fat_file_size;
    7841014    else
    7851015        bts2rd = fs_info->fat.vol.bpc;
    7861016
    787     while ((ret = fat_file_read(mt_entry, fat_fd, (j * bts2rd), bts2rd,
    788                                 fs_info->cl_buf)) != FAT_EOF)
    789     {
     1017    entries_per_block = bts2rd / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
     1018
     1019#if MSDOS_FIND_PRINT
     1020    printf ("MSFS:[1] cn:%i ebp:%li bts2rd:%li lfne:%d nl:%i n:%s\n",
     1021            create_node, entries_per_block, bts2rd, lfn_entries, name_len, name);
     1022#endif
     1023    /*
     1024     * Scan the directory seeing if the file is present. While
     1025     * doing this see if a suitable location can be found to
     1026     * create the entry if the name is not found.
     1027     */
     1028    while ((ret = fat_file_read(mt_entry, fat_fd, (dir_offset * bts2rd),
     1029                                bts2rd, fs_info->cl_buf)) != FAT_EOF)
     1030    {
     1031        bool remainder_empty = false;
     1032#if MSDOS_FIND_PRINT
     1033        printf ("MSFS:[2] dir_offset:%li\n", dir_offset);
     1034#endif
     1035       
    7901036        if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
    7911037            rtems_set_errno_and_return_minus_one(EIO);
     
    7941040
    7951041        /* have to look at the DIR_NAME as "raw" 8-bit data */
    796         for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
     1042        for (dir_entry = 0;
     1043             dir_entry < bts2rd;
     1044             dir_entry += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
    7971045        {
    798             /* is the entry empty ? */
    799             if (((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
    800                  MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) ||
    801                  ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
    802                  MSDOS_THIS_DIR_ENTRY_EMPTY))
     1046            char* entry = (char*) fs_info->cl_buf + dir_entry;
     1047
     1048            /*
     1049             * See if the entry is empty or the remainder of the directory is
     1050             * empty ? Localise to make the code read better.
     1051             */
     1052            bool entry_empty = (*MSDOS_DIR_ENTRY_TYPE(entry) ==
     1053                                MSDOS_THIS_DIR_ENTRY_EMPTY);
     1054            remainder_empty = (*MSDOS_DIR_ENTRY_TYPE(entry) ==
     1055                               MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY);
     1056#if MSDOS_FIND_PRINT
     1057            printf ("MSFS:[3] re:%i ee:%i do:%li de:%li(%ld)\n",
     1058                    remainder_empty, entry_empty, dir_offset,
     1059                    dir_entry, (dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE));
     1060#endif
     1061            /*
     1062             * Remember where the we are, ie the start, so we can come back
     1063             * to here and write the long file name if this is the start of
     1064             * a series of empty entries. If empty_space_count is 0 then
     1065             * we are currently not inside an empty series of entries. It
     1066             * is a count of empty entries.
     1067             */
     1068            if (empty_space_count == 0)
    8031069            {
    804                 /* whether we are looking for an empty entry */
    805                 if (name == NULL)
    806                 {
    807                     /* get current cluster number */
    808                     rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
    809                                         j * bts2rd, &paux->cln);
    810                     if (rc != RC_OK)
    811                         return rc;
    812 
    813                     /* offset is computed in bytes */
    814                     paux->ofs = i;
    815 
    816                     /* write new node entry */
    817                     ret = fat_file_write(mt_entry, fat_fd, j * bts2rd + i,
    818                                          MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
    819                                          (uint8_t *)name_dir_entry);
    820                     if (ret != MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
    821                         return -1;
    822 
    823                     /*
    824                      * we don't update fat_file_size here - it should not
    825                      * increase
    826                      */
    827                     return RC_OK;
    828                 }
    829 
     1070                empty_space_entry = dir_entry;
     1071                empty_space_offset = dir_offset;
     1072            }
     1073
     1074            if (remainder_empty)
     1075            {
     1076#if MSDOS_FIND_PRINT
     1077                printf ("MSFS:[3.1] cn:%i esf:%i\n", create_node, empty_space_found);
     1078#endif
    8301079                /*
    831                  * if name != NULL and there is no more entries in the
     1080                 * If just looking and there is no more entries in the
    8321081                 * directory - return name-not-found
    8331082                 */
    834                 if (((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
    835                      MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY))
     1083                if (!create_node)
    8361084                    return MSDOS_NAME_NOT_FOUND_ERR;
     1085
     1086                /*
     1087                 * Lets go and write the directory entries. If we have not found
     1088                 * any available space add the remaining number of entries to any that
     1089                 * we may have already found that are just before this entry. If more
     1090                 * are needed FAT_EOF is returned by the read and we extend the file.
     1091                 */
     1092                if (!empty_space_found)
     1093                {
     1094                  empty_space_count +=
     1095                    entries_per_block - (dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
     1096                  empty_space_found = true;
     1097#if MSDOS_FIND_PRINT
     1098                  printf ("MSFS:[3.2] esf:%i esc%i\n", empty_space_found, empty_space_count);
     1099#endif
     1100                }
     1101                break;
     1102            }
     1103            else if (entry_empty)
     1104            {
     1105                if (create_node)
     1106                {
     1107                  /*
     1108                   * Remainder is not empty so is this entry empty ?
     1109                   */
     1110                  empty_space_count++;
     1111               
     1112                  if (empty_space_count == (lfn_entries + 1))
     1113                    empty_space_found = true;
     1114                }
     1115#if MSDOS_FIND_PRINT
     1116                printf ("MSFS:[4.1] esc:%li esf:%i\n",
     1117                        empty_space_count, empty_space_found);
     1118#endif
    8371119            }
    8381120            else
    8391121            {
    840                 /* entry not empty and name != NULL -> compare names */
    841                 if (name != NULL)
     1122                /*
     1123                 * A valid entry so handle it.
     1124                 *
     1125                 * If empty space has not been found we need to start the
     1126                 * count again.
     1127                 */
     1128                if (create_node && !empty_space_found)
    8421129                {
    843                     if (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), name,
    844                                 MSDOS_SHORT_NAME_LEN) == 0)
     1130                    empty_space_entry = 0;
     1131                    empty_space_count = 0;
     1132                }
     1133
     1134                /*
     1135                 * Check the attribute to see if the entry is for a long
     1136                 * file name.
     1137                 */
     1138                if ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) ==
     1139                    MSDOS_ATTR_LFN)
     1140                {
     1141                    char* p;
     1142                    int   o;
     1143                    int   i;
     1144#if MSDOS_FIND_PRINT
     1145                    printf ("MSFS:[4.2] lfn:%c entry:%i checksum:%i\n",
     1146                            lfn_start.cln == FAT_FILE_SHORT_NAME ? 't' : 'f',
     1147                            *MSDOS_DIR_ENTRY_TYPE(entry) & MSDOS_LAST_LONG_ENTRY_MASK,
     1148                            *MSDOS_DIR_LFN_CHECKSUM(entry));
     1149#endif
     1150                    /*
     1151                     * If we are not already processing a LFN see if this is
     1152                     * the first entry of a LFN ?
     1153                     */
     1154                    if (lfn_start.cln == FAT_FILE_SHORT_NAME)
     1155                    {
     1156                        lfn_matched = false;
     1157
     1158                        /*
     1159                         * The first entry must have the last long entry
     1160                         * flag set.
     1161                         */
     1162                        if ((*MSDOS_DIR_ENTRY_TYPE(entry) &
     1163                             MSDOS_LAST_LONG_ENTRY) == 0)
     1164                            continue;
     1165
     1166                        /*
     1167                         * Does the number of entries in the LFN directory
     1168                         * entry match the number we expect for this
     1169                         * file name. Note we do not know the number of
     1170                         * characters in the entry so this is check further
     1171                         * on when the characters are checked.
     1172                         */
     1173                        if (lfn_entries != (*MSDOS_DIR_ENTRY_TYPE(entry) &
     1174                                            MSDOS_LAST_LONG_ENTRY_MASK))
     1175                            continue;
     1176                       
     1177                        /*
     1178                         * Get the checksum of the short entry.
     1179                         */
     1180                        lfn_start.cln = dir_offset;
     1181                        lfn_start.ofs = dir_entry;
     1182                        lfn_entry = lfn_entries;
     1183                        lfn_checksum = *MSDOS_DIR_LFN_CHECKSUM(entry);
     1184                       
     1185#if MSDOS_FIND_PRINT
     1186                        printf ("MSFS:[4.3] lfn_checksum:%i\n",
     1187                                *MSDOS_DIR_LFN_CHECKSUM(entry));
     1188#endif
     1189                    }
     1190
     1191                    /*
     1192                     * If the entry number or the check sum do not match
     1193                     * forget this series of long directory entries. These
     1194                     * could be orphaned entries depending on the history
     1195                     * of the disk.
     1196                     */
     1197                    if ((lfn_entry != (*MSDOS_DIR_ENTRY_TYPE(entry) &
     1198                                       MSDOS_LAST_LONG_ENTRY_MASK)) ||
     1199                        (lfn_checksum != *MSDOS_DIR_LFN_CHECKSUM(entry)))
     1200                    {
     1201#if MSDOS_FIND_PRINT
     1202                        printf ("MSFS:[4.4] no match\n");
     1203#endif
     1204                        lfn_start.cln = FAT_FILE_SHORT_NAME;
     1205                        continue;
     1206                    }
     1207
     1208                    lfn_entry--;
     1209                    o = lfn_entry * MSDOS_LFN_LEN_PER_ENTRY;
     1210                    p = entry + 1;
     1211                       
     1212#if MSDOS_FIND_PRINT
     1213                    printf ("MSFS:[5] lfne:%i\n", lfn_entry);
     1214#endif
     1215                    for (i = 0; i < MSDOS_LFN_LEN_PER_ENTRY; i++)
     1216                    {
     1217#if MSDOS_FIND_PRINT > 1
     1218                        printf ("MSFS:[6] o:%i i:%i *p:%c(%02x) name[o + i]:%c(%02x)\n",
     1219                                o, i, *p, *p, name[o + i], name[o + i]);
     1220#endif
     1221                        if (*p == '\0')
     1222                        {
     1223                            /*
     1224                             * If this is the first entry, ie the last part of the
     1225                             * long file name and the length does not match then
     1226                             * the file names do not match.
     1227                             */
     1228                            if (((lfn_entry + 1) == lfn_entries) &&
     1229                                ((o + i) != name_len))
     1230                                lfn_start.cln = FAT_FILE_SHORT_NAME;
     1231                            break;
     1232                        }
     1233                       
     1234                        if (((o + i) >= name_len) || (*p != name[o + i]))
     1235                        {
     1236                            lfn_start.cln = FAT_FILE_SHORT_NAME;
     1237                            break;
     1238                        }
     1239
     1240                        switch (i)
     1241                        {
     1242                            case 4:
     1243                                p += 5;
     1244                                break;
     1245                            case 10:
     1246                                p += 4;
     1247                                break;
     1248                            default:
     1249                                p += 2;
     1250                                break;
     1251                        }
     1252                    }
     1253
     1254                    lfn_matched = ((lfn_entry == 0) &&
     1255                                   (lfn_start.cln != FAT_FILE_SHORT_NAME));
     1256                   
     1257#if MSDOS_FIND_PRINT
     1258                    printf ("MSFS:[8.1] lfn_matched:%i\n", lfn_matched);
     1259#endif
     1260                }
     1261                else
     1262                {
     1263                    /*
     1264                     * SFN entry found.
     1265                     *
     1266                     * If a LFN has been found and it matched check the
     1267                     * entries have all been found and the checksum is
     1268                     * correct. If this is the case return the short file
     1269                     * name entry.
     1270                     */
     1271                    if (lfn_matched)
     1272                    {
     1273                        uint8_t  cs = 0;
     1274                        uint8_t* p = (uint8_t*) MSDOS_DIR_NAME(entry);
     1275                        int      i;
     1276
     1277                        for (i = 0; i < MSDOS_SHORT_NAME_LEN; i++, p++)
     1278                            cs = ((cs & 1) ? 0x80 : 0) + (cs >> 1) + *p;
     1279
     1280                        if (lfn_entry || (lfn_checksum != cs))
     1281                            lfn_matched = false;
     1282                    }
     1283
     1284                    /*
     1285                     * If the long file names matched or the file name is
     1286                     * short and they match then we have the entry. We will not
     1287                     * match a long file name against a short file name because
     1288                     * a long file name that generates a matching short file
     1289                     * name is not a long file name.
     1290                     */
     1291                    if (lfn_matched ||
     1292                        ((name_type == MSDOS_NAME_SHORT) &&
     1293                         (lfn_start.cln == FAT_FILE_SHORT_NAME) &&
     1294                         (memcmp(MSDOS_DIR_NAME(entry),
     1295                                 MSDOS_DIR_NAME(name_dir_entry),
     1296                                 MSDOS_SHORT_NAME_LEN) == 0)))
    8451297                    {
    8461298                        /*
    847                          * we get the entry we looked for - fill auxiliary
    848                          * structure and copy all 32 bytes of the entry
     1299                         * We get the entry we looked for - fill the position
     1300                         * structure and the 32 bytes of the short entry
    8491301                         */
    850                         rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
    851                                             j * bts2rd, &paux->cln);
     1302                        int rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
     1303                                                dir_offset * bts2rd,
     1304                                                &dir_pos->sname.cln);
    8521305                        if (rc != RC_OK)
    8531306                            return rc;
    8541307
    855                         /* offset is computed in bytes */
    856                         paux->ofs = i;
    857                         memcpy(name_dir_entry,(fs_info->cl_buf + i),
     1308                        dir_pos->sname.ofs = dir_entry;
     1309                       
     1310                        if (lfn_start.cln != FAT_FILE_SHORT_NAME)
     1311                        {
     1312                          rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
     1313                                              lfn_start.cln * bts2rd,
     1314                                              &lfn_start.cln);
     1315                          if (rc != RC_OK)
     1316                            return rc;
     1317                        }
     1318               
     1319                        dir_pos->lname.cln = lfn_start.cln;
     1320                        dir_pos->lname.ofs = lfn_start.ofs;
     1321
     1322                        memcpy(name_dir_entry, entry,
    8581323                               MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
    8591324                        return RC_OK;
    8601325                    }
     1326                   
     1327                    lfn_start.cln = FAT_FILE_SHORT_NAME;
     1328                    lfn_matched = false;
    8611329                }
    8621330            }
    8631331        }
    864         j++;
    865     }
    866     return MSDOS_NAME_NOT_FOUND_ERR;
     1332
     1333        if (remainder_empty)
     1334            break;
     1335
     1336        dir_offset++;
     1337    }
     1338
     1339    /*
     1340     * If we are not to create the entry return a not found error.
     1341     */
     1342    if (!create_node)
     1343      return MSDOS_NAME_NOT_FOUND_ERR;
     1344
     1345#if MSDOS_FIND_PRINT
     1346    printf ("MSFS:[8.1] WRITE do:%ld esc:%ld eso:%ld ese:%ld\n",
     1347            dir_offset, empty_space_count, empty_space_offset, empty_space_entry);
     1348#endif
     1349
     1350    /*
     1351     * If a long file name calculate the checksum of the short file name
     1352     * data to place in each long file name entry. First set the short
     1353     * file name to the slot of the SFN entry. This will mean no clashes
     1354     * in this directory.
     1355     */
     1356    lfn_checksum = 0;
     1357    if (name_type == MSDOS_NAME_LONG)
     1358    {
     1359        uint8_t* p = (uint8_t*) MSDOS_DIR_NAME(name_dir_entry);
     1360        int      i;
     1361        int      slot = (((empty_space_offset * bts2rd) + empty_space_entry) /
     1362                         MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) + lfn_entries + 1;
     1363                 
     1364        msdos_short_name_hex(MSDOS_DIR_NAME(name_dir_entry), slot);
     1365
     1366        for (i = 0; i < 11; i++, p++)
     1367            lfn_checksum =
     1368                ((lfn_checksum & 1) ? 0x80 : 0) + (lfn_checksum >> 1) + *p;
     1369    }
     1370
     1371    /*
     1372     * If there is no space available then extend the file. The
     1373     * empty_space_count is a count of empty entries in the currently
     1374     * read cluster so if 0 there is no space. Note, dir_offset will
     1375     * be at the next cluster so we can just make empty_space_offset
     1376     * that value.
     1377     */
     1378    if (empty_space_count == 0)
     1379    {
     1380        read_cluster = true;
     1381        empty_space_offset = dir_offset;
     1382        empty_space_entry = 0;
     1383    }
     1384
     1385    /*
     1386     * Have we read past the empty block ? If so go back and read it again.
     1387     */
     1388    if (dir_offset != empty_space_offset)
     1389        read_cluster = true;
     1390
     1391    /*
     1392     * Handle the entry writes.
     1393     */
     1394    lfn_start.cln = lfn_start.ofs = FAT_FILE_SHORT_NAME;
     1395    lfn_entry = 0;
     1396
     1397#if MSDOS_FIND_PRINT
     1398    printf ("MSFS:[9] read_cluster:%d eso:%ld ese:%ld\n",
     1399            read_cluster, empty_space_offset, empty_space_entry);
     1400#endif
     1401
     1402    /*
     1403     * The one more is the short entry.
     1404     */
     1405    while (lfn_entry < (lfn_entries + 1))
     1406    {
     1407        int length = 0;
     1408       
     1409        if (read_cluster)
     1410        {
     1411          uint32_t new_length;
     1412#if MSDOS_FIND_PRINT
     1413          printf ("MSFS:[9.1] eso:%li\n", empty_space_offset);
     1414#endif
     1415          ret = fat_file_read(mt_entry, fat_fd,
     1416                              (empty_space_offset * bts2rd), bts2rd,
     1417                              fs_info->cl_buf);
     1418
     1419          if (ret != bts2rd)
     1420          {
     1421            if (ret != FAT_EOF)
     1422              rtems_set_errno_and_return_minus_one(EIO);
     1423
     1424#if MSDOS_FIND_PRINT
     1425            printf ("MSFS:[9.2] extending file:%li\n", empty_space_offset);
     1426#endif
     1427            ret = fat_file_extend (mt_entry, fat_fd, empty_space_offset * bts2rd,
     1428                                   &new_length);
     1429                                           
     1430            if (ret != RC_OK)
     1431              return ret;
     1432
     1433#if MSDOS_FIND_PRINT
     1434            printf ("MSFS:[9.3] extended: %d <-> %d\n", new_length, empty_space_offset * bts2rd);
     1435#endif
     1436            if (new_length != (empty_space_offset * bts2rd))
     1437              rtems_set_errno_and_return_minus_one(EIO);
     1438
     1439            memset(fs_info->cl_buf, 0, bts2rd);
     1440
     1441            ret = fat_file_write(mt_entry, fat_fd,
     1442                                 empty_space_offset * bts2rd,
     1443                                 bts2rd, fs_info->cl_buf);
     1444#if MSDOS_FIND_PRINT
     1445            printf ("MSFS:[9.4] clear write: %d\n", ret);
     1446#endif
     1447            if (ret != bts2rd)
     1448              rtems_set_errno_and_return_minus_one(EIO);
     1449          }
     1450        }
     1451       
     1452#if MSDOS_FIND_PRINT
     1453        printf ("MSFS:[10] eso:%li\n", empty_space_offset);
     1454#endif
     1455       
     1456        for (dir_entry = empty_space_entry;
     1457             dir_entry < bts2rd;
     1458             dir_entry += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
     1459        {
     1460            char*       entry = (char*) fs_info->cl_buf + dir_entry;
     1461            char*       p;
     1462            const char* n;
     1463            int         i;
     1464
     1465            length += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
     1466            lfn_entry++;
     1467           
     1468#if MSDOS_FIND_PRINT
     1469            printf ("MSFS:[10] de:%li(%li) length:%i lfn_entry:%i\n",
     1470                    dir_entry, (dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE),
     1471                    length, lfn_entry);
     1472#endif
     1473            /*
     1474             * Time to write the short file name entry.
     1475             */
     1476            if (lfn_entry == (lfn_entries + 1))
     1477            {
     1478                /* get current cluster number */
     1479                int rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
     1480                                        empty_space_offset * bts2rd,
     1481                                        &dir_pos->sname.cln);
     1482                if (rc != RC_OK)
     1483                  return rc;
     1484
     1485                dir_pos->sname.ofs = dir_entry;
     1486
     1487                if (lfn_start.cln != FAT_FILE_SHORT_NAME)
     1488                {
     1489                  rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
     1490                                      lfn_start.cln * bts2rd,
     1491                                      &lfn_start.cln);
     1492                  if (rc != RC_OK)
     1493                    return rc;
     1494                }
     1495               
     1496                dir_pos->lname.cln = lfn_start.cln;
     1497                dir_pos->lname.ofs = lfn_start.ofs;
     1498
     1499                /* write new node entry */
     1500                memcpy (entry, (uint8_t *) name_dir_entry,
     1501                        MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
     1502                break;
     1503            }
     1504
     1505            /*
     1506             * This is a long file name and we need to write
     1507             * a long file name entry. See if this is the
     1508             * first entry written and if so remember the
     1509             * the location of the long file name.
     1510             */
     1511            if (lfn_start.cln == FAT_FILE_SHORT_NAME)
     1512            {
     1513              lfn_start.cln = empty_space_offset;
     1514              lfn_start.ofs = dir_entry;
     1515            }
     1516           
     1517            /*
     1518             * Clear the entry before loading the data.
     1519             */
     1520            memset (entry, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
     1521
     1522            *MSDOS_DIR_LFN_CHECKSUM(entry) = lfn_checksum;
     1523           
     1524            p = entry + 1;
     1525            n = name + (lfn_entries - lfn_entry) * MSDOS_LFN_LEN_PER_ENTRY;
     1526           
     1527            for (i = 0; i < MSDOS_LFN_LEN_PER_ENTRY; i++)
     1528            {
     1529                *p = *n;
     1530                if (*n != 0)
     1531                    n++;
     1532               
     1533                switch (i)
     1534                {
     1535                    case 4:
     1536                        p += 5;
     1537                        break;
     1538                    case 10:
     1539                        p += 4;
     1540                        break;
     1541                    default:
     1542                        p += 2;
     1543                        break;
     1544                }
     1545            }
     1546
     1547            *MSDOS_DIR_ENTRY_TYPE(entry) = (lfn_entries - lfn_entry) + 1;
     1548            if (lfn_entry == 1)
     1549                *MSDOS_DIR_ENTRY_TYPE(entry) |= MSDOS_LAST_LONG_ENTRY;
     1550            *MSDOS_DIR_ATTR(entry) |= MSDOS_ATTR_LFN;
     1551        }
     1552
     1553        ret = fat_file_write(mt_entry, fat_fd,
     1554                             (empty_space_offset * bts2rd) + empty_space_entry,
     1555                             length, fs_info->cl_buf + empty_space_entry);
     1556        if (ret != length)
     1557            rtems_set_errno_and_return_minus_one(EIO);
     1558
     1559        empty_space_offset++;
     1560        empty_space_entry = 0;
     1561        read_cluster = true;
     1562    }
     1563   
     1564    return 0;
    8671565}
    8681566
    8691567/* msdos_find_node_by_cluster_num_in_fat_file --
    8701568 *     Find node with specified number of cluster in fat-file.
     1569 *
     1570 * Note, not updated in the LFN change because it is only used
     1571 *       for . and .. entries and these are always short.
    8711572 *
    8721573 * PARAMETERS:
     
    8861587    fat_file_fd_t                        *fat_fd,
    8871588    uint32_t                              cl4find,
    888     fat_auxiliary_t                      *paux,
     1589    fat_dir_pos_t                        *dir_pos,
    8891590    char                                 *dir_entry
    8901591    )
     
    9121613        for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
    9131614        {
     1615            char* entry = (char*) fs_info->cl_buf + i;
     1616           
    9141617            /* if this and all rest entries are empty - return not-found */
    915             if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
     1618            if ((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
    9161619                MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
    9171620                return MSDOS_NAME_NOT_FOUND_ERR;
    9181621
    919             /* have to look at the DIR_NAME as "raw" 8-bit data */
    9201622            /* if this entry is empty - skip it */
    921             if ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
     1623            if ((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
    9221624                MSDOS_THIS_DIR_ENTRY_EMPTY)
    9231625                continue;
    9241626
    9251627            /* if get a non-empty entry - compare clusters num */
    926             if (MSDOS_EXTRACT_CLUSTER_NUM((fs_info->cl_buf + i)) == cl4find)
     1628            if (MSDOS_EXTRACT_CLUSTER_NUM(entry) == cl4find)
    9271629            {
    9281630                /* on success fill aux structure and copy all 32 bytes */
    9291631                rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, j * bts2rd,
    930                                     &paux->cln);
     1632                                    &dir_pos->sname.cln);
    9311633                if (rc != RC_OK)
    9321634                    return rc;
    9331635
    934                 paux->ofs = i;
    935                 memcpy(dir_entry, fs_info->cl_buf + i,
     1636                dir_pos->sname.ofs = i;
     1637                dir_pos->lname.cln = FAT_FILE_SHORT_NAME;
     1638                dir_pos->lname.ofs = FAT_FILE_SHORT_NAME;
     1639               
     1640                memcpy(dir_entry, entry,
    9361641                       MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
    9371642                return RC_OK;
  • cpukit/libfs/src/dosfs/msdos_mknod.c

    r8c44190a r07d6fd5  
    3737 *
    3838 * PARAMETERS:
    39  *     token   - non-formatted name of a new node
     39 *     name    - file name to create
    4040 *     mode    - node type
    4141 *     dev     - dev
     
    4747 */
    4848int msdos_mknod(
    49     const char                        *token,
     49    const char                        *name,
    5050    mode_t                             mode,
    5151    dev_t                              dev,
     
    5757    msdos_fs_info_t     *fs_info = pathloc->mt_entry->fs_info;
    5858    msdos_token_types_t  type = 0;
    59     char                 new_name[ MSDOS_NAME_MAX + 1 ];
    60     int                  len;
    61 
    62     /* check spelling and format new node name */
    63     msdos_get_token(token, new_name, &len);
    64 
     59   
    6560    /*
    6661     *  Figure out what type of msdos node this is.
     
    8378
    8479    /* Create an MSDOS node */
    85     rc = msdos_creat_node(pathloc, type, new_name, mode, NULL);
     80    rc = msdos_creat_node(pathloc, type, name, strlen(name), mode, NULL);
    8681
    8782    rtems_semaphore_release(fs_info->vol_sema);
  • cpukit/libfs/src/imfs/deviceio.c

    r8c44190a r07d6fd5  
    207207 *  device_lseek
    208208 *
    209  *  This handler eats all lseek() operations.
    210  */
    211 
    212 off_t device_lseek(
    213   rtems_libio_t *iop,
    214   off_t          offset,
     209 *  This handler eats all lseek() operations and does not create
     210 *  an error. It assumes all devices can handle the seek. The
     211 *  writes fail.
     212 */
     213
     214rtems_off64_t device_lseek(
     215  rtems_libio_t *iop,
     216  rtems_off64_t  offset,
    215217  int            whence
    216218)
     
    233235int device_ftruncate(
    234236  rtems_libio_t *iop,
    235   off_t          length
     237  rtems_off64_t  length
    236238)
    237239{
  • cpukit/libfs/src/imfs/imfs.h

    r8c44190a r07d6fd5  
    9999
    100100typedef struct {
    101   off_t      size;             /* size of file in bytes */
    102   block_ptr  indirect;         /* array of 128 data blocks pointers */
    103   block_ptr  doubly_indirect;  /* 128 indirect blocks */
    104   block_ptr  triply_indirect;  /* 128 doubly indirect blocks */
     101  rtems_off64_t size;             /* size of file in bytes */
     102  block_ptr     indirect;         /* array of 128 data blocks pointers */
     103  block_ptr     doubly_indirect;  /* 128 indirect blocks */
     104  block_ptr     triply_indirect;  /* 128 doubly indirect blocks */
    105105} IMFS_memfile_t;
    106106
    107107typedef struct {
    108   off_t      size;             /* size of file in bytes */
    109   block_p    direct;           /* pointer to file image */
     108  rtems_off64_t size;             /* size of file in bytes */
     109  block_p       direct;           /* pointer to file image */
    110110} IMFS_linearfile_t;
    111111
     
    381381extern int memfile_ftruncate(
    382382  rtems_libio_t *iop,               /* IN  */
    383   off_t          length             /* IN  */
     383  rtems_off64_t  length             /* IN  */
    384384);
    385385
     
    401401);
    402402
    403 extern off_t imfs_dir_lseek(
     403extern rtems_off64_t imfs_dir_lseek(
    404404  rtems_libio_t        *iop,              /* IN  */
    405   off_t                 offset,           /* IN  */
     405  rtems_off64_t         offset,           /* IN  */
    406406  int                   whence            /* IN  */
    407407);
     
    445445);
    446446
    447 extern off_t memfile_lseek(
     447extern rtems_off64_t memfile_lseek(
    448448  rtems_libio_t        *iop,        /* IN  */
    449   off_t                 offset,     /* IN  */
     449  rtems_off64_t         offset,     /* IN  */
    450450  int                   whence      /* IN  */
    451451);
     
    484484);
    485485
    486 extern off_t device_lseek(
     486extern rtems_off64_t device_lseek(
    487487  rtems_libio_t *iop,               /* IN  */
    488   off_t          offset,            /* IN  */
     488  rtems_off64_t  offset,            /* IN  */
    489489  int            whence             /* IN  */
    490490);
     
    492492extern int device_ftruncate(
    493493  rtems_libio_t *iop,               /* IN  */
    494   off_t          length             /* IN  */
     494  rtems_off64_t  length             /* IN  */
    495495);
    496496
  • cpukit/libfs/src/imfs/imfs_directory.c

    r8c44190a r07d6fd5  
    183183 */
    184184
    185 off_t imfs_dir_lseek(
     185rtems_off64_t imfs_dir_lseek(
    186186  rtems_libio_t  *iop,
    187   off_t           offset,
     187  rtems_off64_t   offset,
    188188  int             whence
    189189)
  • cpukit/libfs/src/imfs/imfs_fifo.c

    r8c44190a r07d6fd5  
    120120}
    121121
    122 off_t IMFS_fifo_lseek(
     122rtems_off64_t IMFS_fifo_lseek(
    123123  rtems_libio_t *iop,
    124   off_t         offset,
    125   int           whence
     124  rtems_off64_t  offset,
     125  int            whence
    126126)
    127127{
  • cpukit/libfs/src/imfs/memfile.c

    r8c44190a r07d6fd5  
    215215 */
    216216
    217 off_t memfile_lseek(
     217rtems_off64_t memfile_lseek(
    218218  rtems_libio_t   *iop,
    219   off_t            offset,
     219  rtems_off64_t    offset,
    220220  int              whence
    221221)
     
    252252int memfile_ftruncate(
    253253  rtems_libio_t        *iop,
    254   off_t                 length
     254  rtems_off64_t         length
    255255)
    256256{
  • cpukit/libfs/src/nfsclient/src/nfs.c

    r8c44190a r07d6fd5  
    27382738#endif
    27392739
    2740 static off_t nfs_file_lseek(
     2740static rtems_off64_t nfs_file_lseek(
    27412741        rtems_libio_t *iop,
    2742         off_t          length,
     2742        rtems_off64_t  length,
    27432743        int            whence
    27442744)
     
    27712771}
    27722772
    2773 static off_t nfs_dir_lseek(
     2773static rtems_off64_t nfs_dir_lseek(
    27742774        rtems_libio_t *iop,
    2775         off_t          length,
     2775        rtems_off64_t  length,
    27762776        int            whence
    27772777)
     
    28192819struct  stat
    28202820{
    2821                 dev_t     st_dev;
    2822                 ino_t     st_ino;
    2823                 mode_t    st_mode;
    2824                 nlink_t   st_nlink;
    2825                 uid_t     st_uid;
    2826                 gid_t     st_gid;
    2827                 dev_t     st_rdev;
    2828                 off_t    st_size;
     2821                dev_t         st_dev;
     2822                ino_t         st_ino;
     2823                mode_t        st_mode;
     2824                nlink_t       st_nlink;
     2825                uid_t         st_uid;
     2826                gid_t         st_gid;
     2827                dev_t         st_rdev;
     2828                rtems_off64_t st_size;
    28292829                /* SysV/sco doesn't have the rest... But Solaris, eabi does.  */
    28302830#if defined(__svr4__) && !defined(__PPC__) && !defined(__sun__)
    2831                 time_t    st_atime;
    2832                 time_t    st_mtime;
    2833                 time_t    st_ctime;
     2831                time_t        st_atime;
     2832                time_t        st_mtime;
     2833                time_t        st_ctime;
    28342834#else
    2835                 time_t    st_atime;
    2836                 long      st_spare1;
    2837                 time_t    st_mtime;
    2838                 long      st_spare2;
    2839                 time_t    st_ctime;
    2840                 long      st_spare3;
    2841                 long      st_blksize;
    2842                 long      st_blocks;
    2843                 long  st_spare4[2];
     2835                time_t        st_atime;
     2836                long          st_spare1;
     2837                time_t        st_mtime;
     2838                long          st_spare2;
     2839                time_t        st_ctime;
     2840                long          st_spare3;
     2841                long          st_blksize;
     2842                long          st_blocks;
     2843                long      st_spare4[2];
    28442844#endif
    28452845};
     
    30103010static int nfs_file_ftruncate(
    30113011        rtems_libio_t *iop,
    3012         off_t          length
     3012        rtems_off64_t  length
    30133013)
    30143014{
  • cpukit/libmisc/shell/main_msdosfmt.c

    r8c44190a r07d6fd5  
    4343    media:               0,
    4444    quick_format:        TRUE,
    45     cluster_align:       0
     45    cluster_align:       0,
     46    info_level:          0
    4647  };
    4748 
     
    5253    if (argv[arg][0] == '-') {
    5354      switch (argv[arg][1]) {
    54         case 'v':
     55        case 'V':
    5556          arg++;
    5657          if (arg == argc) {
     
    5960          }
    6061          rqdata.VolLabel = argv[arg];
     62          break;
     63
     64        case 's':
     65          arg++;
     66          if (arg == argc) {
     67            fprintf (stderr, "error: sectors per cluster count.\n");
     68            return 1;
     69          }
     70          rqdata.sectors_per_cluster = rtems_shell_str2int(argv[arg]);
    6171          break;
    6272         
     
    91101          break;
    92102
     103        case 'v':
     104          rqdata.info_level++;
     105          break;
     106         
    93107        default:
    94108          fprintf (stderr, "error: invalid option: %s\n", argv[arg]);
     
    112126 
    113127  printf ("msdos format: %s\n", driver);
     128
     129  if (rqdata.info_level)
     130  {
     131    printf (" %-20s: %s\n", "OEMName", "RTEMS");
     132    printf (" %-20s: %s\n", "VolLabel", "RTEMSDisk");
     133    printf (" %-20s: %i\n", "sectors per cluster", rqdata.sectors_per_cluster);
     134    printf (" %-20s: %i\n", "fats", rqdata.fat_num);
     135    printf (" %-20s: %i\n", "files per root dir", rqdata.files_per_root_dir);
     136    printf (" %-20s: %i\n", "fat type", rqdata.fattype);
     137    printf (" %-20s: %d\n", "media", rqdata.media);
     138    printf (" %-20s: %d\n", "quick_format", rqdata.quick_format);
     139    printf (" %-20s: %i\n", "cluster align", rqdata.cluster_align);
     140  }
    114141 
    115142  if (msdos_format (driver, &rqdata) < 0) {
  • cpukit/libnetworking/lib/ftpfs.c

    r8c44190a r07d6fd5  
    987987
    988988/* Dummy version to let fopen( *,"w") work properly */
    989 static int rtems_ftpfs_ftruncate( rtems_libio_t *iop, off_t count)
     989static int rtems_ftpfs_ftruncate( rtems_libio_t *iop, rtems_off64_t count)
    990990{
    991991  return 0;
  • cpukit/libnetworking/lib/tftpDriver.c

    r8c44190a r07d6fd5  
    985985static int rtems_tftp_ftruncate(
    986986    rtems_libio_t   *iop __attribute__((unused)),
    987     off_t           count __attribute__((unused))
     987    rtems_off64_t    count __attribute__((unused))
    988988)
    989989{
Note: See TracChangeset for help on using the changeset viewer.