From 2e7b6dbbb5dfba02c3c45a7976250f6786b11857 Mon Sep 17 00:00:00 2001 From: Jennifer Averett Date: Tue, 5 Aug 2003 14:05:56 +0000 Subject: 2003-08-04 Thomas Doerfler PR 441/filesystem *src/dosfs/msdos.h: add rename support to DOSFS *src/dosfs/msdos_create.c: add rename support to DOSFS *src/dosfs/msdos_file.c: add rename support to DOSFS *src/dosfs/msdos_init.c: add rename support to DOSFS *src/dosfs/msdos_mknod.c: add rename support to DOSFS --- cpukit/libfs/src/dosfs/msdos_create.c | 149 +++++++++++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 4 deletions(-) (limited to 'cpukit/libfs/src/dosfs/msdos_create.c') diff --git a/cpukit/libfs/src/dosfs/msdos_create.c b/cpukit/libfs/src/dosfs/msdos_create.c index c50935021b..4606598a8e 100644 --- a/cpukit/libfs/src/dosfs/msdos_create.c +++ b/cpukit/libfs/src/dosfs/msdos_create.c @@ -40,6 +40,8 @@ * type - new node type (file or directory) * name - new node name * mode - mode + * link_info - fs_info of existing node for a pseudo "hard-link" + * (see msdos_file.c, msdos_link for documentation) * * RETURNS: * RC_OK on success, or -1 if error occured (errno set appropriately). @@ -50,7 +52,8 @@ msdos_creat_node( rtems_filesystem_location_info_t *parent_loc, msdos_node_type_t type, char *name, - mode_t mode + mode_t mode, + const fat_file_fd_t *link_fd ) { int rc = RC_OK; @@ -62,8 +65,11 @@ msdos_creat_node( unsigned16 time_val = 0; unsigned16 date = 0; fat_auxiliary_t aux; - unsigned char new_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE]; + unsigned char new_node [MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE]; unsigned char dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2]; + unsigned char link_node [MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE]; + unsigned32 sec = 0; + unsigned32 byte = 0; memset(new_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); memset(dot_dotdot, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2); @@ -86,10 +92,58 @@ msdos_creat_node( /* initialize directory/file size */ *MSDOS_DIR_FILE_SIZE(new_node) = MSDOS_INIT_DIR_SIZE; - if (type == MSDOS_DIRECTORY) + if (type == MSDOS_DIRECTORY){ *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_DIRECTORY; - else + } + else if (type == MSDOS_HARD_LINK) { + /* + * when we establish a (temporary) hard link, + * we must copy some information from the original + * node to the newly created + */ + /* + * read the original directory entry + */ + sec = fat_cluster_num_to_sector_num(parent_loc->mt_entry, + link_fd->info_cln); + sec += (link_fd->info_ofs >> fs_info->fat.vol.sec_log2); + byte = (link_fd->info_ofs & (fs_info->fat.vol.bps - 1)); + + ret = _fat_block_read(parent_loc->mt_entry, + sec, byte, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE, + link_node); + if (ret < 0) { + return -1; + } + /* + * copy various attributes + */ + *MSDOS_DIR_ATTR(new_node) =*MSDOS_DIR_ATTR(link_node); + *MSDOS_DIR_CRT_TIME_TENTH(new_node)=*MSDOS_DIR_CRT_TIME_TENTH(link_node); + *MSDOS_DIR_CRT_TIME(new_node) =*MSDOS_DIR_CRT_TIME(link_node); + *MSDOS_DIR_CRT_DATE(new_node) =*MSDOS_DIR_CRT_DATE(link_node); + + /* + * copy/set "file size", "first cluster" + */ + *MSDOS_DIR_FILE_SIZE(new_node) =*MSDOS_DIR_FILE_SIZE(link_node); + + *MSDOS_DIR_FIRST_CLUSTER_LOW(new_node) = + *MSDOS_DIR_FIRST_CLUSTER_LOW(link_node); + *MSDOS_DIR_FIRST_CLUSTER_HI(new_node) = + *MSDOS_DIR_FIRST_CLUSTER_HI(link_node); + /* + * set "archive bit" due to changes + */ + *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE; + /* + * set "last access" date to today + */ + *MSDOS_DIR_LAST_ACCESS_DATE(new_node) = CT_LE_W(date); + } + else { /* regular file... */ *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE; + } /* * find free space in the parent directory and write new initialized @@ -204,3 +258,90 @@ err: 0xE5); return rc; } + +/* msdos_file_link -- + * Replacement for a file "link" operation. + * MSDOS FAT FS does not support links, but this call is needed to + * allow "rename" operations. The current NEWLIB rename performs a link + * from the old to the new name and then deletes the old filename. + * + * This pseudo-"link" operation will create a new directory entry, + * copy the file size and cluster information from the "old" + * to the "new" directory entry and then clear the file size and cluster + * info from the "old" filename, leaving this file as + * a valid, but empty entry. + * + * When this "link" call is part of a "rename" sequence, the "old" + * entry will be deleted in a subsequent "rmnod" call + * + * This function has been implemented by Thomas Doerfler, + * + * + * PARAMETERS: + * to_loc - node description for "existing" node + * par_loc - node description for "new" node + * token - name of new node + * + * RETURNS: + * RC_OK on success, or -1 if error occured (errno set appropriately) + */ +int +msdos_file_link(rtems_filesystem_location_info_t *to_loc, + rtems_filesystem_location_info_t *par_loc, + const char *token +) +{ + int rc = RC_OK; + rtems_status_code sc = RTEMS_SUCCESSFUL; + msdos_fs_info_t *fs_info = to_loc->mt_entry->fs_info; + fat_file_fd_t *to_fat_fd = to_loc->node_access; + fat_file_fd_t *par_fat_fd = par_loc->node_access; + char new_name[ MSDOS_NAME_MAX + 1 ]; + int len; + + /* + * check spelling and format new node name + */ + if (MSDOS_NAME != msdos_get_token(token, new_name, &len)) { + set_errno_and_return_minus_one(ENAMETOOLONG); + } + /* + * verify, that the existing node can be linked to + * check that nodes are in same FS/volume? + */ + if (to_loc->mt_entry->fs_info != par_loc->mt_entry->fs_info) { + set_errno_and_return_minus_one(EXDEV); + } + /* + * lock volume + */ + 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); + + + /* + * create new directory entry as "hard link", + * copying relevant info from existing file + */ + rc = msdos_creat_node(par_loc,MSDOS_HARD_LINK,new_name,S_IFREG, + to_loc->node_access); + /* + * set file size and first cluster number of old entry to 0 + */ + if (rc == RC_OK) { + to_fat_fd->fat_file_size = 0; + to_fat_fd->cln = FAT_EOF; + rc = msdos_set_first_cluster_num(to_loc->mt_entry, to_fat_fd); + if (rc == RC_OK) { + rc = msdos_set_file_size(par_loc->mt_entry, to_fat_fd); + } + } + /* + * FIXME: check error/abort handling + */ + rtems_semaphore_release(fs_info->vol_sema); + return rc; +} + -- cgit v1.2.3