📄 msdos_dir.c
字号:
/* * MSDOS directory handlers implementation * * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru> * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.com/license/LICENSE. * * @(#) $Id: msdos_dir.c,v 1.1.2.3 2003/09/04 18:47:02 joel Exp $ */#if HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#include <unistd.h>#include <assert.h>#include <errno.h>#include <rtems/libio_.h>#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#include "fat.h"#include "fat_fat_operations.h"#include "fat_file.h"#include "msdos.h"/* msdos_dir_open -- * Open fat-file which correspondes to the directory being opened and * set offset field of file control block to zero. * * PARAMETERS: * iop - file control block * pathname - name * flag - flags * mode - mode * * RETURNS: * RC_OK, if directory opened successfully, or -1 if error occured (errno * set apropriately) */int msdos_dir_open(rtems_libio_t *iop, const char *pathname, unsigned32 flag, unsigned32 mode){ int rc = RC_OK; rtems_status_code sc = RTEMS_SUCCESSFUL; msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info; fat_file_fd_t *fat_fd = iop->file_info; sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT, MSDOS_VOLUME_SEMAPHORE_TIMEOUT); if (sc != RTEMS_SUCCESSFUL) set_errno_and_return_minus_one( EIO ); rc = fat_file_reopen(fat_fd); if (rc != RC_OK) { rtems_semaphore_release(fs_info->vol_sema); return rc; } iop->offset = 0; rtems_semaphore_release(fs_info->vol_sema); return RC_OK;} /* msdos_dir_close -- * Close fat-file which correspondes to the directory being closed * * PARAMETERS: * iop - file control block * * RETURNS: * RC_OK, if directory closed successfully, or -1 if error occured (errno * set apropriately. */int msdos_dir_close(rtems_libio_t *iop){ int rc = RC_OK; rtems_status_code sc = RTEMS_SUCCESSFUL; msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info; fat_file_fd_t *fat_fd = iop->file_info; sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT, MSDOS_VOLUME_SEMAPHORE_TIMEOUT); if (sc != RTEMS_SUCCESSFUL) set_errno_and_return_minus_one( EIO ); rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd); if (rc != RC_OK) { rtems_semaphore_release(fs_info->vol_sema); return rc; } rtems_semaphore_release(fs_info->vol_sema); return RC_OK;}/* msdos_format_dirent_with_dot -- * This routine convert a (short) MSDOS filename as present on disk * (fixed 8+3 characters, filled with blanks, without separator dot) * to a "normal" format, with between 0 and 8 name chars, * a separating dot and up to 3 extension characters * Rules to work: * - copy any (0-8) "name" part characters that are non-blank * - if an extension exists, append a dot * - copy any (0-3) non-blank extension characters * - append a '\0' (dont count it for the rturn code * * PARAMETERS: * dst: pointer to destination char array (must be big enough) * src: pointer to source characters * * * RETURNS: * the number of bytes (without trailing '\0'(written to destination */static ssize_t msdos_format_dirent_with_dot(char *dst,const char *src){ ssize_t len; int i; const char *src_tmp; /* * find last non-blank character of base name */ for ((i = MSDOS_SHORT_BASE_LEN , src_tmp = src + MSDOS_SHORT_BASE_LEN-1); ((i > 0) && (*src_tmp == ' ')); i--,src_tmp--) {}; /* * copy base name to destination */ src_tmp = src; len = i; while (i-- > 0) { *dst++ = *src_tmp++; } /* * find last non-blank character of extension */ for ((i = MSDOS_SHORT_EXT_LEN , src_tmp = src + MSDOS_SHORT_BASE_LEN+MSDOS_SHORT_EXT_LEN-1); ((i > 0) && (*src_tmp == ' ')); i--,src_tmp--) {}; /* * extension is not empty */ if (i > 0) { *dst++ = '.'; /* append dot */ len += i + 1; /* extension + dot */ src_tmp = src + MSDOS_SHORT_BASE_LEN; while (i-- > 0) { *dst++ = *src_tmp++; len++; } } *dst = '\0'; /* terminate string */ return len;}/* msdos_dir_read -- * This routine will read the next directory entry based on the directory * offset. The offset should be equal to -n- time the size of an * individual dirent structure. If n is not an integer multiple of the * sizeof a dirent structure, an integer division will be performed to * determine directory entry that will be returned in the buffer. Count * should reflect -m- times the sizeof dirent bytes to be placed in the * buffer. * If there are not -m- dirent elements from the current directory * position to the end of the exisiting file, the remaining entries will * be placed in the buffer and the returned value will be equal to * -m actual- times the size of a directory entry. * * PARAMETERS: * iop - file control block * buffer - buffer provided by user * count - count of bytes to read * * RETURNS: * the number of bytes read on success, or -1 if error occured (errno * set apropriately). */ssize_t msdos_dir_read(rtems_libio_t *iop, void *buffer, unsigned32 count){ int rc = RC_OK; rtems_status_code sc = RTEMS_SUCCESSFUL; msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info; fat_file_fd_t *fat_fd = iop->file_info; fat_file_fd_t *tmp_fat_fd = NULL; struct dirent tmp_dirent; unsigned32 start = 0; ssize_t ret = 0; unsigned32 cmpltd = 0; unsigned32 j = 0, i = 0; unsigned32 bts2rd = 0; unsigned32 cur_cln = 0; /* * cast start and count - protect against using sizes that are not exact * multiples of the -dirent- size. These could result in unexpected * results */ start = iop->offset / sizeof(struct dirent); count = (count / sizeof(struct dirent)) * sizeof(struct dirent); /* * optimization: we know that root directory for FAT12/16 volumes is * sequential set of sectors and any cluster is sequential set of sectors * too, so read such set of sectors is quick operation for low-level IO * layer. */ bts2rd = (FAT_FD_OF_ROOT_DIR(fat_fd) && (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) ? fat_fd->fat_file_size : fs_info->fat.vol.bpc; sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT, MSDOS_VOLUME_SEMAPHORE_TIMEOUT); if (sc != RTEMS_SUCCESSFUL) set_errno_and_return_minus_one(EIO); while (count > 0) { /* * fat-file is already opened by open call, so read it * Always read directory fat-file from the beggining because of MSDOS * directories feature :( - we should count elements currently * present in the directory because there may be holes :) */ ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, (j * bts2rd), bts2rd, fs_info->cl_buf); if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) { rtems_semaphore_release(fs_info->vol_sema); set_errno_and_return_minus_one(EIO); } for (i = 0; i < ret; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) { if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) { rtems_semaphore_release(fs_info->vol_sema); return cmpltd; } if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == MSDOS_THIS_DIR_ENTRY_EMPTY) continue; /* * skip active entries until get the entry to start from */ if (start) { start--; continue; } /* * Move the entry to the return buffer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -