diff options
Diffstat (limited to 'c/src/libfs/src/dosfs/msdos_misc.c')
-rw-r--r-- | c/src/libfs/src/dosfs/msdos_misc.c | 1087 |
1 files changed, 0 insertions, 1087 deletions
diff --git a/c/src/libfs/src/dosfs/msdos_misc.c b/c/src/libfs/src/dosfs/msdos_misc.c deleted file mode 100644 index fe2779f7a8..0000000000 --- a/c/src/libfs/src/dosfs/msdos_misc.c +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * Miscellaneous routines implementation for MSDOS filesystem - * - * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia - * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.OARcorp.com/rtems/license.html. - * - * @(#) $Id$ - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdlib.h> -#include <sys/time.h> -#include <unistd.h> -#include <string.h> -#include <assert.h> -#include <rtems/libio_.h> - -#include "fat.h" -#include "fat_fat_operations.h" -#include "fat_file.h" - -#include "msdos.h" - -/* This copied from Linux */ -static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 }; - /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */ - -#undef CONFIG_ATARI - -/* MS-DOS "device special files" */ -static const char *reserved_names[] = { -#ifndef CONFIG_ATARI /* GEMDOS is less stupid */ - "CON ","PRN ","NUL ","AUX ", - "LPT1 ","LPT2 ","LPT3 ","LPT4 ", - "COM1 ","COM2 ","COM3 ","COM4 ", -#endif - NULL }; - -static char bad_chars[] = "*?<>|\""; -#ifdef CONFIG_ATARI -/* GEMDOS is less restrictive */ -static char bad_if_strict[] = " "; -#else -static char bad_if_strict[] = "+=,; "; -#endif - -/* The following three functions copied from Linux */ -/* - * Formats an MS-DOS file name. Rejects invalid names - * - * conv is relaxed/normal/strict, name is proposed name, - * len is the length of the proposed name, res is the result name, - * dotsOK is if hidden files get dots. - */ -int -msdos_format_name(char conv, const char *name, int len, char *res, - char dotsOK) -{ - char *walk; - const char **reserved; - unsigned char c; - int space; - if (name[0] == '.') { /* dotfile because . and .. already done */ - if (!dotsOK) return -EINVAL; - /* Get rid of dot - test for it elsewhere */ - name++; len--; - } -#ifndef CONFIG_ATARI - space = 1; /* disallow names that _really_ start with a dot */ -#else - space = 0; /* GEMDOS does not care */ -#endif - c = 0; - for (walk = res; len && walk-res < 8; walk++) { - c = *name++; - len--; - if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL; - if (conv == 's' && strchr(bad_if_strict,c)) return -EINVAL; - if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL; - if (c < ' ' || c == ':' || c == '\\') return -EINVAL; -/* 0xE5 is legal as a first character, but we must substitute 0x05 */ -/* because 0xE5 marks deleted files. Yes, DOS really does this. */ -/* It seems that Microsoft hacked DOS to support non-US characters */ -/* after the 0xE5 character was already in use to mark deleted files. */ - if((res==walk) && (c==0xE5)) c=0x05; - if (c == '.') break; - space = (c == ' '); - *walk = (c >= 'a' && c <= 'z') ? c-32 : c; - } - if (space) return -EINVAL; - if (conv == 's' && len && c != '.') { - c = *name++; - len--; - if (c != '.') return -EINVAL; - } - while (c != '.' && len--) c = *name++; - if (c == '.') { - while (walk-res < 8) *walk++ = ' '; - while (len > 0 && walk-res < MSDOS_NAME_MAX) { - c = *name++; - len--; - if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL; - if (conv == 's' && strchr(bad_if_strict,c)) - return -EINVAL; - if (c < ' ' || c == ':' || c == '\\') - return -EINVAL; - if (c == '.') { - if (conv == 's') - return -EINVAL; - break; - } - if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL; - space = c == ' '; - *walk++ = c >= 'a' && c <= 'z' ? c-32 : c; - } - if (space) return -EINVAL; - if (conv == 's' && len) return -EINVAL; - } - while (walk-res < MSDOS_NAME_MAX) *walk++ = ' '; - for (reserved = reserved_names; *reserved; reserved++) - if (!strncmp(res,*reserved,8)) return -EINVAL; - return 0; -} - -/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70) */ -unsigned int -msdos_date_dos2unix(unsigned short time_val,unsigned short date) -{ - int month,year,secs; - - month = ((date >> 5) & 15)-1; - year = date >> 9; - secs = (time_val & 31)*2+60*((time_val >> 5) & 63)+ - (time_val >> 11)*3600+86400* - ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && - month < 2 ? 1 : 0)+3653); - /* days since 1.1.70 plus 80's leap day */ - - return secs; -} - - -/* Convert linear UNIX date to a MS-DOS time/date pair */ -void msdos_date_unix2dos(int unix_date, - unsigned short *time_val, - unsigned short *date) -{ - int day,year,nl_day,month; - - *time_val = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+ - (((unix_date/3600) % 24) << 11); - day = unix_date/86400-3652; - year = day/365; - if ((year+3)/4+365*year > day) year--; - day -= (year+3)/4+365*year; - if (day == 59 && !(year & 3)) { - nl_day = day; - month = 2; - } - else { - nl_day = (year & 3) || day <= 59 ? day : day-1; - for (month = 0; month < 12; month++) - if (day_n[month] > nl_day) break; - } - *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9); -} - - -/* msdos_get_token -- - * Routine to get a token (name or separator) from the path. - * - * PARAMETERS: - * path - path to get token from - * ret_token - returned token - * token_len - length of returned token - * - * RETURNS: - * token type, token and token length - * - */ -msdos_token_types_t -msdos_get_token(const char *path, char *ret_token, int *token_len) -{ - int rc = RC_OK; - register int i = 0; - msdos_token_types_t type = MSDOS_NAME; - char token[MSDOS_NAME_MAX_WITH_DOT+1]; - register char c; - - /* - * Copy a name into token. (Remember NULL is a token.) - */ - c = path[i]; - while ( (!msdos_is_separator(c)) && (i <= MSDOS_NAME_MAX_WITH_DOT) ) - { - token[i] = c; - if ( i == MSDOS_NAME_MAX_WITH_DOT ) - return MSDOS_INVALID_TOKEN; - if ( !msdos_is_valid_name_char(c) ) - return MSDOS_INVALID_TOKEN; - c = path [++i]; - } - - /* - * Copy a seperator into token. - */ - if ( i == 0 ) - { - token[i] = c; - if ( token[i] != '\0' ) - { - i++; - type = MSDOS_CURRENT_DIR; - } - else - type = MSDOS_NO_MORE_PATH; - } - else if (token[ i-1 ] != '\0') - token[i] = '\0'; - - /* - * Set token_len to the number of characters copied. - */ - *token_len = i; - - /* - * If we copied something that was not a seperator see if - * it was a special name. - */ - if ( type == MSDOS_NAME ) - { - if ( strcmp( token, "..") == 0 ) - { - strcpy(ret_token, MSDOS_DOTDOT_NAME); - type = MSDOS_UP_DIR; - return type; - } - - if ( strcmp( token, "." ) == 0 ) - { - strcpy(ret_token, MSDOS_DOT_NAME); - type = MSDOS_CURRENT_DIR; - return type; - } - - rc = msdos_format_name('r', token, *token_len, ret_token, 0); - if ( rc != RC_OK ) - return MSDOS_INVALID_TOKEN; - } - ret_token[MSDOS_NAME_MAX] = '\0'; - return type; -} - - -/* msdos_find_name -- - * Find the node which correspondes to the name, open fat-file which - * correspondes to the found node and close fat-file which correspondes - * to the node we searched in. - * - * PARAMETERS: - * parent_loc - parent node description - * name - name to find - * - * RETURNS: - * RC_OK and updated 'parent_loc' on success, or -1 if error - * occured (errno set apropriately) - * - */ -int -msdos_find_name( - rtems_filesystem_location_info_t *parent_loc, - char *name - ) -{ - int rc = RC_OK; - msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info; - fat_file_fd_t *fat_fd = NULL; - fat_auxiliary_t aux; - unsigned short time_val = 0; - unsigned short date = 0; - unsigned char node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE]; - - memset(node_entry, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); - - /* - * find the node which correspondes to the name in the directory pointed by - * 'parent_loc' - */ - rc = msdos_get_name_node(parent_loc, name, &aux, node_entry); - if (rc != RC_OK) - return rc; - - /* open fat-file corresponded to the found node */ - rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd); - if (rc != RC_OK) - return rc; - - /* - * I don't like this if, but: we should do it , or should write new file - * size and first cluster num to the disk after each write operation - * (even if one byte is written - that is TOO non-optimize) because - * otherwise real values of these fields stored in fat-file descriptor - * may be accidentely rewritten with wrong values stored on the disk - */ - if (fat_fd->links_num == 1) - { - fat_fd->info_cln = aux.cln; - fat_fd->info_ofs = aux.ofs; - fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(node_entry); - fat_fd->first_char = *MSDOS_DIR_NAME(node_entry); - - time_val = *MSDOS_DIR_WRITE_TIME(node_entry); - date = *MSDOS_DIR_WRITE_DATE(node_entry); - - fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(time_val), CF_LE_W(date)); - - if ((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_DIRECTORY) - { - fat_fd->fat_file_type = FAT_DIRECTORY; - fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT; - - rc = fat_file_size(parent_loc->mt_entry, fat_fd); - if (rc != RC_OK) - { - fat_file_close(parent_loc->mt_entry, fat_fd); - return rc; - } - } - else - { - fat_fd->fat_file_size = CF_LE_L(*MSDOS_DIR_FILE_SIZE(node_entry)); - fat_fd->fat_file_type = FAT_FILE; - fat_fd->size_limit = MSDOS_MAX_FILE_SIZE; - } - - /* these data is not actual for zero-length fat-file */ - fat_fd->map.file_cln = 0; - fat_fd->map.disk_cln = fat_fd->cln; - - if ((fat_fd->fat_file_size != 0) && - (fat_fd->fat_file_size <= fs_info->fat.vol.bpc)) - { - fat_fd->map.last_cln = fat_fd->cln; - } - else - { - fat_fd->map.last_cln = FAT_UNDEFINED_VALUE; - } - } - - /* close fat-file corresponded to the node we searched in */ - rc = fat_file_close(parent_loc->mt_entry, parent_loc->node_access); - if (rc != RC_OK) - { - fat_file_close(parent_loc->mt_entry, fat_fd); - return rc; - } - - /* update node_info_ptr field */ - parent_loc->node_access = fat_fd; - - return rc; -} - -/* msdos_get_name_node -- - * This routine is used in two ways: for a new mode creation (a) or for - * search the node which correspondes to the name parameter (b). - * In case (a) 'name' should be set up to NULL and 'name_dir_entry' should - * point to initialized 32 bytes structure described a new node. - * In case (b) 'name' should contain a valid string. - * - * (a): reading fat-file which correspondes to directory we are going to - * create node in. If free slot is found write contents of - * 'name_dir_entry' into it. If reach end of fat-file and no free - * slot found, write 32 bytes to the end of fat-file. - * - * (b): reading fat-file which correspondes to directory and trying to - * find slot with the name field == 'name' parameter - * - * - * PARAMETERS: - * parent_loc - node description to create node in or to find name in - * name - NULL or name to find - * paux - identify a node location on the disk - - * cluster num and offset inside the cluster - * name_dir_entry - node to create/placeholder for found node (IN/OUT) - * - * RETURNS: - * RC_OK, filled aux_struct_ptr and name_dir_entry on success, or -1 if - * error occured (errno set apropriately) - * - */ -int -msdos_get_name_node( - rtems_filesystem_location_info_t *parent_loc, - char *name, - fat_auxiliary_t *paux, - char *name_dir_entry - ) -{ - int rc = RC_OK; - ssize_t ret = 0; - msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info; - fat_file_fd_t *fat_fd = parent_loc->node_access; - unsigned32 dotdot_cln = 0; - - /* find name in fat-file which correspondes to the directory */ - rc = msdos_find_name_in_fat_file(parent_loc->mt_entry, fat_fd, name, paux, - name_dir_entry); - if ((rc != RC_OK) && (rc != MSDOS_NAME_NOT_FOUND_ERR)) - return rc; - - /* if we search for valid name and name not found -> return */ - if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name != NULL)) - return rc; - - /* - * if we try to create new entry and the directory is not big enough - * currently - try to enlarge directory - */ - if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name == NULL)) - { - ret = fat_file_write(parent_loc->mt_entry, fat_fd, - fat_fd->fat_file_size, - MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE, - name_dir_entry); - if (ret == -1) - return -1; - - /* on success directory is enlarged by a new cluster */ - fat_fd->fat_file_size += fs_info->fat.vol.bpc; - - /* get cluster num where a new node located */ - rc = fat_file_ioctl(parent_loc->mt_entry, fat_fd, F_CLU_NUM, - fat_fd->fat_file_size - 1, &paux->cln); - - if (rc != RC_OK) - return rc; - - /* - * if new cluster allocated succesfully then new node is at very - * beginning of the cluster (offset is computed in bytes) - */ - paux->ofs = 0; - return RC_OK; - } - - /* - * if we have deal with ".." - it is a special case :((( - * - * Really, we should return cluster num and offset not of ".." slot, but - * slot which correspondes to real directory name. - */ - if ((rc == RC_OK) && (name != NULL)) - { - if (strncmp(name, MSDOS_DOTDOT_NAME, MSDOS_SHORT_NAME_LEN) == 0) - { - dotdot_cln = MSDOS_EXTRACT_CLUSTER_NUM((name_dir_entry)); - - /* are we right under root dir ? */ - if (dotdot_cln == 0) - { - /* - * we can relax about first_char field - it never should be - * used for root dir - */ - paux->cln = FAT_ROOTDIR_CLUSTER_NUM; - paux->ofs = 0; - } - else - { - rc = msdos_get_dotdot_dir_info_cluster_num_and_offset( - parent_loc->mt_entry, - dotdot_cln, - paux, - name_dir_entry - ); - if (rc != RC_OK) - return rc; - } - } - } - return rc; -} - -/* - * msdos_get_dotdot_dir_info_cluster_num_and_offset - * - * Unfortunately, in general, we cann't work here in fat-file ideologic - * (open fat_file "..", get ".." and ".", open "..", find an entry ...) - * because if we open - * fat-file ".." it may happend that we have two different fat-file - * descriptors ( for real name of directory and ".." name ) for a single - * file ( cluster num of both pointers to the same cluster ) - * But...we do it because we protected by semaphore - * - */ - -/* msdos_get_dotdot_dir_info_cluster_num_and_offset -- - * Get cluster num and offset not of ".." slot, but slot which correspondes - * to real directory name. - * - * PARAMETERS: - * mt_entry - mount table entry - * cln - data cluster num extracted drom ".." slot - * paux - identify a node location on the disk - - * number of cluster and offset inside the cluster - * dir_entry - placeholder for found node - * - * RETURNS: - * RC_OK, filled 'paux' and 'dir_entry' on success, or -1 if error occured - * (errno set apropriately) - * - */ -int -msdos_get_dotdot_dir_info_cluster_num_and_offset( - rtems_filesystem_mount_table_entry_t *mt_entry, - unsigned32 cln, - fat_auxiliary_t *paux, - char *dir_entry - ) -{ - int rc = RC_OK; - msdos_fs_info_t *fs_info = mt_entry->fs_info; - fat_file_fd_t *fat_fd = NULL; - unsigned char dot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE]; - unsigned char dotdot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE]; - unsigned char cur_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE]; - unsigned32 cl4find = 0; - - memset(dot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); - memset(dotdot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); - memset(cur_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); - - /* - * open fat-file corresponded to ".." - */ - rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd); - if (rc != RC_OK) - return rc; - - fat_fd->info_cln = paux->cln; - fat_fd->info_ofs = paux->ofs; - fat_fd->cln = cln; - fat_fd->fat_file_type = FAT_DIRECTORY; - fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT; - - fat_fd->map.file_cln = 0; - fat_fd->map.disk_cln = fat_fd->cln; - - rc = fat_file_size(mt_entry, fat_fd); - if (rc != RC_OK) - { - fat_file_close(mt_entry, fat_fd); - return rc; - } - - /* find "." node in opened directory */ - rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOT_NAME, paux, - dot_node); - - if (rc != RC_OK) - { - fat_file_close(mt_entry, fat_fd); - return rc; - } - - /* find ".." node in opened directory */ - rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOTDOT_NAME, paux, - dotdot_node); - - if (rc != RC_OK) - { - fat_file_close(mt_entry, fat_fd); - return rc; - } - - cl4find = MSDOS_EXTRACT_CLUSTER_NUM(dot_node); - - /* close fat-file corresponded to ".." directory */ - rc = fat_file_close(mt_entry, fat_fd); - if ( rc != RC_OK ) - return rc; - - if ( (MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0) - { - /* - * we handle root dir for all FAT types in the same way with the - * ordinary directories ( through fat_file_* calls ) - */ - paux->cln = FAT_ROOTDIR_CLUSTER_NUM; - paux->ofs = 0; - } - - /* open fat-file corresponded to second ".." */ - rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd); - if (rc != RC_OK) - return rc; - - fat_fd->info_cln = paux->cln; - fat_fd->info_ofs = paux->ofs; - - if ((MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0) - fat_fd->cln = fs_info->fat.vol.rdir_cl; - else - fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node); - - fat_fd->fat_file_type = FAT_DIRECTORY; - fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT; - - fat_fd->map.file_cln = 0; - fat_fd->map.disk_cln = fat_fd->cln; - - rc = fat_file_size(mt_entry, fat_fd); - if (rc != RC_OK) - { - fat_file_close(mt_entry, fat_fd); - return rc; - } - - /* in this directory find slot with specified cluster num */ - rc = msdos_find_node_by_cluster_num_in_fat_file(mt_entry, fat_fd, cl4find, - paux, dir_entry); - if (rc != RC_OK) - { - fat_file_close(mt_entry, fat_fd); - return rc; - } - rc = fat_file_close(mt_entry, fat_fd); - return rc; -} - - -/* msdos_set_dir_wrt_time_and_date -- - * Write last write date and time for a file to the disk (to corresponded - * 32bytes node) - * - * PARAMETERS: - * mt_entry - mount table entry - * fat_fd - fat-file descriptor - * - * RETURNS: - * RC_OK on success, or -1 if error occured (errno set apropriately). - * - */ -int -msdos_set_dir_wrt_time_and_date( - rtems_filesystem_mount_table_entry_t *mt_entry, - fat_file_fd_t *fat_fd - ) -{ - ssize_t ret1 = 0, ret2 = 0; - msdos_fs_info_t *fs_info = mt_entry->fs_info; - unsigned short time_val; - unsigned short date; - unsigned32 sec = 0; - unsigned32 byte = 0; - - msdos_date_unix2dos(fat_fd->mtime, &time_val, &date); - - /* - * calculate input for _fat_block_write: convert (cluster num, offset) to - * (sector num, new offset) - */ - sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln); - sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2); - /* byte points to start of 32bytes structure */ - byte = fat_fd->info_ofs & (fs_info->fat.vol.bps - 1); - - time_val = CT_LE_W(time_val); - ret1 = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_WTIME_OFFSET, - 2, (char *)(&time_val)); - date = CT_LE_W(date); - ret2 = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_WDATE_OFFSET, - 2, (char *)(&date)); - - if ( (ret1 < 0) || (ret2 < 0) ) - return -1; - - return RC_OK; -} - -/* msdos_set_first_cluster_num -- - * Write number of first cluster of the file to the disk (to corresponded - * 32bytes slot) - * - * PARAMETERS: - * mt_entry - mount table entry - * fat_fd - fat-file descriptor - * - * RETURNS: - * RC_OK on success, or -1 if error occured - * - */ -int -msdos_set_first_cluster_num( - rtems_filesystem_mount_table_entry_t *mt_entry, - fat_file_fd_t *fat_fd - ) -{ - ssize_t ret1 = 0, ret2 = 0; - msdos_fs_info_t *fs_info = mt_entry->fs_info; - unsigned32 new_cln = fat_fd->cln; - unsigned16 le_cl_low = 0; - unsigned16 le_cl_hi = 0; - unsigned32 sec = 0; - unsigned32 byte = 0; - - /* - * calculate input for _fat_block_write: convert (cluster num, offset) to - * (sector num, new offset) - */ - sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln); - sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2); - /* byte from points to start of 32bytes structure */ - byte = fat_fd->info_ofs & (fs_info->fat.vol.bps - 1); - - le_cl_low = CT_LE_W((unsigned16)(new_cln & 0x0000FFFF)); - ret1 = _fat_block_write(mt_entry, sec, - byte + MSDOS_FIRST_CLUSTER_LOW_OFFSET, 2, - (char *)(&le_cl_low)); - le_cl_hi = CT_LE_W((unsigned16)((new_cln & 0xFFFF0000) >> 16)); - ret2 = _fat_block_write(mt_entry, sec, - byte + MSDOS_FIRST_CLUSTER_HI_OFFSET, 2, - (char *)(&le_cl_hi)); - if ( (ret1 < 0) || (ret2 < 0) ) - return -1; - - return RC_OK; -} - - -/* msdos_set_file size -- - * Write file size of the file to the disk (to corresponded 32bytes slot) - * - * PARAMETERS: - * mt_entry - mount table entry - * fat_fd - fat-file descriptor - * - * RETURNS: - * RC_OK on success, or -1 if error occured (errno set apropriately). - * - */ -int -msdos_set_file_size( - rtems_filesystem_mount_table_entry_t *mt_entry, - fat_file_fd_t *fat_fd - ) -{ - ssize_t ret = 0; - msdos_fs_info_t *fs_info = mt_entry->fs_info; - unsigned32 le_new_length = 0; - unsigned32 sec = 0; - unsigned32 byte = 0; - - sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln); - sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2); - byte = (fat_fd->info_ofs & (fs_info->fat.vol.bps - 1)); - - le_new_length = CT_LE_L((fat_fd->fat_file_size)); - ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_SIZE_OFFSET, 4, - (char *)(&le_new_length)); - if ( ret < 0 ) - return -1; - - return RC_OK; -} - -/* - * We should not check whether this routine is called for root dir - it - * never can happend - */ - -/* msdos_set_first_char4file_name -- - * Write first character of the name of the file to the disk (to - * corresponded 32bytes slot) - * - * PARAMETERS: - * mt_entry - mount table entry - * cl - number of cluster - * ofs - offset inside cluster - * fchar - character to set up - * - * RETURNS: - * RC_OK on success, or -1 if error occured (errno set apropriately) - * - */ -int -msdos_set_first_char4file_name( - rtems_filesystem_mount_table_entry_t *mt_entry, - unsigned32 cl, - unsigned32 ofs, - unsigned char fchar - ) -{ - ssize_t ret = 0; - msdos_fs_info_t *fs_info = mt_entry->fs_info; - unsigned32 sec = 0; - unsigned32 byte = 0; - - sec = fat_cluster_num_to_sector_num(mt_entry, cl); - sec += (ofs >> fs_info->fat.vol.sec_log2); - byte = (ofs & (fs_info->fat.vol.bps - 1)); - - ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_NAME_OFFSET, 1, - &fchar); - if ( ret < 0) - return -1; - - return RC_OK; -} - -/* msdos_dir_is_empty -- - * Check whether directory which correspondes to the fat-file descriptor is - * empty. - * - * PARAMETERS: - * mt_entry - mount table entry - * fat_fd - fat-file descriptor - * ret_val - placeholder for result - * - * RETURNS: - * RC_OK on success, or -1 if error occured - * - */ -int -msdos_dir_is_empty( - rtems_filesystem_mount_table_entry_t *mt_entry, - fat_file_fd_t *fat_fd, - rtems_boolean *ret_val - ) -{ - ssize_t ret = 0; - msdos_fs_info_t *fs_info = mt_entry->fs_info; - unsigned32 j = 0, i = 0; - - /* dir is not empty */ - *ret_val = FALSE; - - while ((ret = fat_file_read(mt_entry, fat_fd, j * fs_info->fat.vol.bps, - fs_info->fat.vol.bps, - fs_info->cl_buf)) != FAT_EOF) - { - if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) - return -1; - - assert(ret == fs_info->fat.vol.bps); - - for (i = 0; - i < fs_info->fat.vol.bps; - i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) - { - if (((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == - MSDOS_THIS_DIR_ENTRY_EMPTY) || - (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), MSDOS_DOT_NAME, - MSDOS_SHORT_NAME_LEN) == 0) || - (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), - MSDOS_DOTDOT_NAME, - MSDOS_SHORT_NAME_LEN) == 0)) - continue; - - if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == - MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) - { - *ret_val = TRUE; - return RC_OK; - } - return RC_OK; - } - j++; - } - *ret_val = TRUE; - return RC_OK; -} - - -/* msdos_find_name_in_fat_file -- - * This routine is used in two ways: for a new mode creation (a) or for - * search the node which correspondes to the 'name' parameter (b). - * In case (a) name should be set up to NULL and 'name_dir_entry' should - * point to initialized 32 bytes structure described a new node. - * In case (b) 'name' should contain a valid string. - * - * (a): reading fat-file corresponded to directory we are going to create - * node in. If found free slot write contents of name_dir_entry into - * it. - * - * (b): reading fat-file corresponded to directory and trying to find slot - * with the name field == name parameter - * - * PARAMETERS: - * mt_entry - mount table entry - * fat_fd - fat-file descriptor - * name - NULL or name to find - * paux - identify a node location on the disk - - * number of cluster and offset inside the cluster - * name_dir_entry - node to create/placeholder for found node - * - * RETURNS: - * RC_OK on success, or error code if error occured (errno set - * appropriately) - * - */ -int -msdos_find_name_in_fat_file( - rtems_filesystem_mount_table_entry_t *mt_entry, - fat_file_fd_t *fat_fd, - char *name, - fat_auxiliary_t *paux, - char *name_dir_entry - ) -{ - int rc = RC_OK; - ssize_t ret = 0; - msdos_fs_info_t *fs_info = mt_entry->fs_info; - unsigned32 i = 0, j = 0; - unsigned32 bts2rd = 0; - - if (FAT_FD_OF_ROOT_DIR(fat_fd) && - (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) - bts2rd = fat_fd->fat_file_size; - else - bts2rd = fs_info->fat.vol.bpc; - - while ((ret = fat_file_read(mt_entry, fat_fd, (j * bts2rd), bts2rd, - fs_info->cl_buf)) != FAT_EOF) - { - if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) - set_errno_and_return_minus_one(EIO); - - assert(ret == bts2rd); - - for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) - { - /* is the entry empty ? */ - if (((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == - MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) || - ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == - MSDOS_THIS_DIR_ENTRY_EMPTY)) - { - /* whether we are looking for an empty entry */ - if (name == NULL) - { - /* get current cluster number */ - rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, - j * bts2rd, &paux->cln); - if (rc != RC_OK) - return rc; - - /* offset is computed in bytes */ - paux->ofs = i; - - /* write new node entry */ - ret = fat_file_write(mt_entry, fat_fd, j * bts2rd + i, - MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE, - name_dir_entry); - if (ret != MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) - return -1; - - /* - * we don't update fat_file_size here - it should not - * increase - */ - return RC_OK; - } - - /* - * if name != NULL and there is no more entries in the - * directory - return name-not-found - */ - if (((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == - MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)) - return MSDOS_NAME_NOT_FOUND_ERR; - } - else - { - /* entry not empty and name != NULL -> compare names */ - if (name != NULL) - { - if (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), name, - MSDOS_SHORT_NAME_LEN) == 0) - { - /* - * we get the entry we looked for - fill auxiliary - * structure and copy all 32 bytes of the entry - */ - rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, - j * bts2rd, &paux->cln); - if (rc != RC_OK) - return rc; - - /* offset is computed in bytes */ - paux->ofs = i; - memcpy(name_dir_entry,(fs_info->cl_buf + i), - MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); - return RC_OK; - } - } - } - } - j++; - } - return MSDOS_NAME_NOT_FOUND_ERR; -} - -/* msdos_find_node_by_cluster_num_in_fat_file -- - * Find node with specified number of cluster in fat-file. - * - * PARAMETERS: - * mt_entry - mount table entry - * fat_fd - fat-file descriptor - * cl4find - number of cluster to find - * paux - identify a node location on the disk - - * cluster num and offset inside the cluster - * dir_entry - placeholder for found node - * - * RETURNS: - * RC_OK on success, or error code if error occured - * - */ -int -msdos_find_node_by_cluster_num_in_fat_file( - rtems_filesystem_mount_table_entry_t *mt_entry, - fat_file_fd_t *fat_fd, - unsigned32 cl4find, - fat_auxiliary_t *paux, - char *dir_entry - ) -{ - int rc = RC_OK; - ssize_t ret = 0; - msdos_fs_info_t *fs_info = mt_entry->fs_info; - unsigned32 bts2rd = 0; - unsigned32 i = 0, j = 0; - - if (FAT_FD_OF_ROOT_DIR(fat_fd) && - (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) - bts2rd = fat_fd->fat_file_size; - else - bts2rd = fs_info->fat.vol.bpc; - - while ((ret = fat_file_read(mt_entry, fat_fd, j * bts2rd, bts2rd, - fs_info->cl_buf)) != FAT_EOF) - { - if ( ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE ) - set_errno_and_return_minus_one( EIO ); - - assert(ret == bts2rd); - - for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) - { - /* if this and all rest entries are empty - return not-found */ - if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == - MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) - return MSDOS_NAME_NOT_FOUND_ERR; - - /* if this entry is empty - skip it */ - if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == - MSDOS_THIS_DIR_ENTRY_EMPTY) - continue; - - /* if get a non-empty entry - compare clusters num */ - if (MSDOS_EXTRACT_CLUSTER_NUM((fs_info->cl_buf + i)) == cl4find) - { - /* on success fill aux structure and copy all 32 bytes */ - rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, j * bts2rd, - &paux->cln); - if (rc != RC_OK) - return rc; - - paux->ofs = i; - memcpy(dir_entry, fs_info->cl_buf + i, - MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); - return RC_OK; - } - } - j++; - } - return MSDOS_NAME_NOT_FOUND_ERR; -} |