Mercurial > ecos
changeset 1818:5663e2763ba6
* src/fatfs.c:
* src/fatfs_supp.c:
* include/fatfs.h (NEW):
* tests/fileio1.c:
* cdl/fatfs.cdl: Added configurable support for FAT filesystem
attributes.
* src/fatfs.c: Added code to setinfo to allow performing a
file-system sync
| author | asl |
|---|---|
| date | Fri, 22 Oct 2004 14:10:21 +0000 |
| parents | df5dcf4cdc1a |
| children | 082e09d84412 |
| files | packages/fs/fat/current/ChangeLog packages/fs/fat/current/cdl/fatfs.cdl packages/fs/fat/current/include/fatfs.h packages/fs/fat/current/src/fatfs.c packages/fs/fat/current/src/fatfs.h packages/fs/fat/current/src/fatfs_supp.c packages/fs/fat/current/tests/fileio1.c |
| diffstat | 7 files changed, 350 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/fs/fat/current/ChangeLog +++ b/packages/fs/fat/current/ChangeLog @@ -1,3 +1,17 @@ +2004-10-17 David Brennan <eCos@brennanhome.com> + + * src/fatfs.c: + * src/fatfs_supp.c: + * include/fatfs.h (NEW): + * tests/fileio1.c: + * cdl/fatfs.cdl: Added configurable support for FAT filesystem + attributes. + +2004-10-13 David Brennan <eCos@brennanhome.com> + + * src/fatfs.c: Added code to setinfo to allow performing a + file-system sync + 2004-10-06 David Brennan <eCos@brennanhome.com> * tests/fileio1.c: Added include of <stdio.h> to fix compiler
--- a/packages/fs/fat/current/cdl/fatfs.cdl +++ b/packages/fs/fat/current/cdl/fatfs.cdl @@ -48,7 +48,7 @@ cdl_package CYGPKG_FS_FAT { display "FAT filesystem" - include_dir cyg/fatfs + include_dir cyg/fs requires CYGPKG_IO_FILEIO @@ -57,7 +57,6 @@ cdl_package CYGPKG_FS_FAT { requires CYGINT_ISO_ERRNO_CODES requires CYGPKG_MEMALLOC requires CYGPKG_BLOCK_LIB -# requires CYGFUN_LIBC_STRING_BSD_FUNCS implements CYGINT_IO_FILEIO_FS @@ -105,6 +104,14 @@ cdl_package CYGPKG_FS_FAT { sanity checks in node cache code." } + cdl_option CYGCFG_FS_FAT_USE_ATTRIBUTES { + display "Support for FAT FS file attributes" + flavor bool + default_value 0 + description "This option controls if the FAT filesystem supports + or honors the FAT filesystem file attributes." + } + # -------------------------------------------------------------------- cdl_option CYGPKG_FS_FAT_TESTS {
new file mode 100644 --- /dev/null +++ b/packages/fs/fat/current/include/fatfs.h @@ -0,0 +1,84 @@ +#ifndef CYGONCE_CYG_FS_FAT_H +#define CYGONCE_CYG_FS_FAT_H +//============================================================================= +// +// fatfs.h +// +// FAT FS attributes and stat information +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2004 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): David Brennam <eCos@brennanhome.com> +// Contributors: +// Date: 2004-10-22 +// Purpose: +// Description: This header contains attributes and stat like mode +// information for FAT filesystems. +// +// Usage: +// #include <cyg/fs/fatfs.h> +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= +// ------------------------------------------------------------------------- +// FAT filesystem dir entry attributes + +#define S_FATFS_RDONLY (0x01) // Read only +#define S_FATFS_HIDDEN (0x02) // Hidden +#define S_FATFS_SYSTEM (0x04) // System +#define S_FATFS_VOLUME (0x08) // Volume label +#define S_FATFS_DIR (0x10) // Subdirectory +#define S_FATFS_ARCHIVE (0x20) // Needs archiving + +// Mode bits which are allowed to be changed by attrib +#define S_FATFS_ATTRIB (S_FATFS_RDONLY | S_FATFS_HIDDEN | S_FATFS_SYSTEM | \ + S_FATFS_ARCHIVE) +// ------------------------------------------------------------------------- +// mode FAT dir entry attributes macros + +#define S_FATFS_ISRDONLY(__mode) ((__mode) & S_FATFS_RDONLY) +#define S_FATFS_ISHIDDEN(__mode) ((__mode) & S_FATFS_HIDDEN) +#define S_FATFS_ISSYSTEM(__mode) ((__mode) & S_FATFS_SYSTEM) +#define S_FATFS_ISVOLUME(__mode) ((__mode) & S_FATFS_VOLUME) +#define S_FATFS_ISDIR(__mode) ((__mode) & S_FATFS_DIR) +#define S_FATFS_ISARCHIVE(__mode) ((__mode) & S_FATFS_ARCHIVE) + +#endif // CYGONCE_CYG_FS_FAT_H +// End of fatfs.h +
--- a/packages/fs/fat/current/src/fatfs.c +++ b/packages/fs/fat/current/src/fatfs.c @@ -73,6 +73,7 @@ #include <cyg/fileio/fileio.h> #include <cyg/io/io.h> #include <blib/blib.h> +#include <cyg/fs/fatfs.h> #include "fatfs.h" @@ -629,6 +630,13 @@ fatfs_open(cyg_mtab_entry *mte, if (S_ISDIR(node->dentry.mode)) return EISDIR; +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES + // if the file is read only and is opened for writing + // fail with permission error + if (S_FATFS_ISRDONLY(node->dentry.attrib) && (mode & O_WRONLY)) + return EACCES; +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES + // Allocate file object private data and // make a reference to this file node @@ -678,6 +686,12 @@ fatfs_unlink(cyg_mtab_entry *mte, if (ds.node->refcnt > 0) return EBUSY; +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES + // if the file is read only fail with permission error + if (S_FATFS_ISRDONLY(ds.node->dentry.attrib)) + return EPERM; +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES + err = fatfs_delete_file(disk, &ds.node->dentry); if (err == ENOERR) fatfs_node_free(disk, ds.node); @@ -789,6 +803,12 @@ fatfs_rename(cyg_mtab_entry *mte, if (err != ENOERR) return err; +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES + // if the file is read only fail with permission error + if (S_FATFS_ISRDONLY(ds1.node->dentry.attrib)) + return EPERM; +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES + // Protect the found nodes from being reused // by the search for the ds2 dir/node pair fatfs_node_ref(disk, ds1.dir); @@ -983,6 +1003,10 @@ fatfs_stat(cyg_mtab_entry *mte, // Fill in the status buf->st_mode = ds.node->dentry.mode; +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES + if (!S_FATFS_ISRDONLY(ds.node->dentry.attrib)) + buf->st_mode |= (S_IWUSR | S_IWGRP | S_IWOTH); +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES buf->st_ino = (ino_t) ds.node->dentry.cluster; buf->st_dev = 0; buf->st_nlink = 1; @@ -996,9 +1020,75 @@ fatfs_stat(cyg_mtab_entry *mte, return ENOERR; } +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES +// ------------------------------------------------------------------------- +// fatfs_set_attrib() +// Set FAT file system attributes for specified file + +static int +fatfs_set_attrib(cyg_mtab_entry *mte, + cyg_dir dir, + const char *name, + const cyg_fs_attrib_t new_attrib) +{ + fatfs_disk_t *disk = (fatfs_disk_t *) mte->data; + fatfs_dirsearch_t ds; + int err; + + CYG_TRACE4(TFS, "chmod mte=%p dir=%p name='%s' buf=%x", + mte, dir, name, new_attrib); + + // Verify new_mode is valid + if ((new_attrib & S_FATFS_ATTRIB) != new_attrib) + return EINVAL; + + init_dirsearch(&ds, disk, (fatfs_node_t *) dir, name); + + err = fatfs_find(&ds); + if (err != ENOERR) + return err; + + // Change the "changeable" mode bits for the file. + ds.node->dentry.attrib = + (ds.node->dentry.attrib & (~S_FATFS_ATTRIB)) | new_attrib; + + return fatfs_write_dir_entry(disk,&ds.node->dentry); +} + +// ------------------------------------------------------------------------- +// fatfs_get_attrib() +// Set FAT file system attributes for specified file + +static int +fatfs_get_attrib(cyg_mtab_entry *mte, + cyg_dir dir, + const char *name, + cyg_fs_attrib_t * const file_attrib) +{ + fatfs_disk_t *disk = (fatfs_disk_t *) mte->data; + fatfs_dirsearch_t ds; + int err; + + CYG_TRACE4(TFS, "chmod mte=%p dir=%p name='%s' buf=%x", + mte, dir, name, new_attrib); + + init_dirsearch(&ds, disk, (fatfs_node_t *) dir, name); + + err = fatfs_find(&ds); + if (err != ENOERR) + return err; + + // Get the attribute field + CYG_CHECK_DATA_PTR(file_attrib,"Invalid destination attribute pointer"); + *file_attrib = ds.node->dentry.attrib; + + return ENOERR; +} +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES + // ------------------------------------------------------------------------- // fatfs_getinfo() -// Getinfo. Nothing to support here at present. +// Getinfo. Support for attrib static int fatfs_getinfo(cyg_mtab_entry *mte, @@ -1008,14 +1098,27 @@ fatfs_getinfo(cyg_mtab_entry *mte, void *buf, int len) { + int err = EINVAL; + CYG_TRACE6(TFS, "getinfo mte=%p dir=%p name='%s' key=%d buf=%p len=%d", mte, dir, name, key, buf, len); - return EINVAL; + switch( key ) + { +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES + case FS_INFO_ATTRIB: + err = fatfs_get_attrib(mte, dir, name, (cyg_fs_attrib_t*)buf); + break; +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES + default: + err = EINVAL; + break; + } + return err; } // ------------------------------------------------------------------------- // fatfs_setinfo() -// Setinfo. Nothing to support here at present. +// Setinfo. Support for fssync and attrib static int fatfs_setinfo(cyg_mtab_entry *mte, @@ -1025,9 +1128,26 @@ fatfs_setinfo(cyg_mtab_entry *mte, void *buf, int len) { - CYG_TRACE6(TFS, "getinfo mte=%p dir=%p name='%s' key=%d buf=%p len=%d", + int err = EINVAL; + + CYG_TRACE6(TFS, "setinfo mte=%p dir=%p name='%s' key=%d buf=%p len=%d", mte, dir, name, key, buf, len); - return EINVAL; + + switch( key ) + { + case FS_INFO_SYNC: + err = cyg_blib_sync(&(((fatfs_disk_t *) mte->data)->blib)); + break; +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES + case FS_INFO_ATTRIB: + err = fatfs_set_attrib(mte, dir, name, *(cyg_fs_attrib_t *)buf); + break; +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES + default: + err = EINVAL; + break; + } + return err; } //==========================================================================
--- a/packages/fs/fat/current/src/fatfs.h +++ b/packages/fs/fat/current/src/fatfs.h @@ -124,6 +124,9 @@ typedef struct fatfs_dir_entry_s cyg_uint32 cluster; // First cluster number cyg_uint32 parent_cluster; // First cluster of parent dentry fatfs_data_pos_t disk_pos; // Position of dir entry on disk +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES + cyg_fs_attrib_t attrib; // Attribute bits for DOS compatability +#endif //CYGCFG_FS_FAT_USE_ATTRIBUTES } fatfs_dir_entry_t; typedef struct fatfs_node_s
--- a/packages/fs/fat/current/src/fatfs_supp.c +++ b/packages/fs/fat/current/src/fatfs_supp.c @@ -53,6 +53,7 @@ #include <cyg/infra/cyg_trac.h> #include <cyg/infra/diag.h> #include <cyg/io/io.h> +#include <cyg/fs/fatfs.h> #include <blib/blib.h> #include <sys/types.h> @@ -64,24 +65,14 @@ // FAT defines & macros // ------------------------------------------------------------------------- -// FAT dir entry attributes - -#define DENTRY_ATTR_RDONLY 0x01 // Read only -#define DENTRY_ATTR_HIDDEN 0x02 // Hidden -#define DENTRY_ATTR_SYSTEM 0x04 // System -#define DENTRY_ATTR_VOLUME 0x08 // Volume label -#define DENTRY_ATTR_DIR 0x10 // Subdirectory -#define DENTRY_ATTR_ARCHIVE 0x20 // Needs archiving - -// ------------------------------------------------------------------------- // FAT dir entry attributes macros -#define DENTRY_IS_RDONLY(_dentry_) ((_dentry_)->attr & DENTRY_ATTR_RDONLY) -#define DENTRY_IS_HIDDEN(_dentry_) ((_dentry_)->attr & DENTRY_ATTR_HIDDEN) -#define DENTRY_IS_SYSTEM(_dentry_) ((_dentry_)->attr & DENTRY_ATTR_SYSTEM) -#define DENTRY_IS_VOLUME(_dentry_) ((_dentry_)->attr & DENTRY_ATTR_VOLUME) -#define DENTRY_IS_DIR(_dentry_) ((_dentry_)->attr & DENTRY_ATTR_DIR) -#define DENTRY_IS_ARCHIVE(_dentry_) ((_dentry_)->attr & DENTRY_ATTR_ARCHIVE) +#define DENTRY_IS_RDONLY(_dentry_) (S_FATFS_ISRDONLY((_dentry_)->attr)) +#define DENTRY_IS_HIDDEN(_dentry_) (S_FATFS_ISHIDDEN((_dentry_)->attr)) +#define DENTRY_IS_SYSTEM(_dentry_) (S_FATFS_ISSYSTEM((_dentry_)->attr)) +#define DENTRY_IS_VOLUME(_dentry_) (S_FATFS_ISVOLUME((_dentry_)->attr)) +#define DENTRY_IS_DIR(_dentry_) (S_FATFS_ISDIR((_dentry_)->attr)) +#define DENTRY_IS_ARCHIVE(_dentry_) (S_FATFS_ISARCHIVE((_dentry_)->attr)) #define DENTRY_IS_DELETED(_dentry_) \ (0xE5 == (cyg_uint8)((_dentry_)->name[0])) @@ -1624,6 +1615,10 @@ raw_to_dentry(fat_raw_dir_entry_t *raw_d else dentry->mode = __stat_mode_REG; +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES + dentry->attrib = raw_dentry->attr; +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES + date_dos2unix(raw_dentry->crt_time, raw_dentry->crt_date, &dentry->ctime); date_dos2unix(0, raw_dentry->acc_date, &dentry->atime); date_dos2unix(raw_dentry->wrt_time, raw_dentry->wrt_date, &dentry->mtime); @@ -1644,9 +1639,13 @@ dentry_to_raw(fatfs_dir_entry_t *dentry, set_raw_dentry_filename(raw_dentry, dentry->filename, 0); if (__stat_mode_DIR == dentry->mode) - raw_dentry->attr = DENTRY_ATTR_DIR; + raw_dentry->attr = S_FATFS_DIR; else - raw_dentry->attr = DENTRY_ATTR_ARCHIVE; + raw_dentry->attr = S_FATFS_ARCHIVE; +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES + raw_dentry->attr = dentry->attrib; +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES + date_unix2dos(dentry->ctime, &raw_dentry->crt_time, &raw_dentry->crt_date); date_unix2dos(dentry->atime, NULL, &raw_dentry->acc_date); @@ -1808,6 +1807,14 @@ init_dir_entry(fatfs_dir_entry_t *dentry dentry->filename[namelen] = '\0'; dentry->mode = mode; + +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES + if (S_ISDIR(dentry->mode)) + dentry->attrib = S_FATFS_DIR; + else + dentry->attrib = S_FATFS_ARCHIVE; +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES + dentry->ctime = dentry->atime = dentry->mtime = cyg_timestamp(); @@ -1939,6 +1946,9 @@ fatfs_get_root_dir_entry(fatfs_disk_t *d CYG_CHECK_DATA_PTRC(dentry); dentry->mode = __stat_mode_DIR; +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES + dentry->attrib = S_FATFS_DIR; +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES dentry->size = disk->fat_root_dir_size; dentry->ctime = 0; dentry->atime = 0; @@ -2389,7 +2399,7 @@ fatfs_rename_file(fatfs_disk_t *dis // If we moved a directory, we also have to correct the '..' entry - if (__stat_mode_DIR == target->mode) + if ( S_ISDIR(target->mode) ) { fat_raw_dir_entry_t raw_cdentry; fatfs_data_pos_t pos;
--- a/packages/fs/fat/current/tests/fileio1.c +++ b/packages/fs/fat/current/tests/fileio1.c @@ -60,6 +60,7 @@ #include <pkgconf/hal.h> #include <pkgconf/kernel.h> #include <pkgconf/io_fileio.h> +#include <pkgconf/fs_fat.h> #include <cyg/kernel/ktypes.h> // base kernel types #include <cyg/infra/cyg_trac.h> // tracing macros @@ -77,6 +78,7 @@ #include <cyg/infra/testcase.h> #include <cyg/infra/diag.h> // HAL polled output +#include <cyg/fs/fatfs.h> @@ -288,6 +290,26 @@ static void checkfile( char *name ) if( err < 0 ) SHOW_RESULT( close, err ); } +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES +//========================================================================== + +static void checkattrib(const char *name, + const cyg_fs_attrib_t test_attrib ) +{ + int err; + cyg_fs_attrib_t file_attrib; + + diag_printf("<INFO>: check attrib %s\n",name); + + err = cyg_fs_get_attrib(name, &file_attrib); + if( err != 0 ) SHOW_RESULT( stat, err ); + + if ( (file_attrib & S_FATFS_ATTRIB) != test_attrib ) + diag_printf("<FAIL>: attrib %s incorrect\n\tExpected %x Was %x\n", + name,test_attrib,(file_attrib & S_FATFS_ATTRIB)); +} +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES + //========================================================================== static void copyfile( char *name2, char *name1 ) @@ -643,6 +665,70 @@ void fileio1_main( CYG_ADDRESS id ) if( err < 0 ) SHOW_RESULT( umount, err ); #endif +#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES + // Create file + diag_printf("<INFO>: create /foo\n"); + createfile( "/foo", 20257 ); + + // Verify it is created with archive bit set + checkattrib( "/foo", S_FATFS_ARCHIVE ); + + // Make it System + diag_printf("<INFO>: attrib -A+S /foo\n"); + err = cyg_fs_set_attrib( "/foo", S_FATFS_SYSTEM ); + if( err < 0 ) SHOW_RESULT( chmod system , err ); + + // Verify it is now System + checkattrib( "/foo", S_FATFS_SYSTEM ); + + // Make it Hidden + diag_printf("<INFO>: attrib -S+H /foo\n"); + err = cyg_fs_set_attrib( "/foo", S_FATFS_HIDDEN ); + if( err < 0 ) SHOW_RESULT( chmod system , err ); + + // Verify it is now Hidden + checkattrib( "/foo", S_FATFS_HIDDEN ); + + // Make it Read-only + diag_printf("<INFO>: attrib -H+R /foo\n"); + err = cyg_fs_set_attrib( "/foo", S_FATFS_RDONLY ); + if( err < 0 ) SHOW_RESULT( chmod system , err ); + + // Verify it is now Read-only + checkattrib( "/foo", S_FATFS_RDONLY ); + + // Verify we cannot unlink a read-only file + diag_printf("<INFO>: unlink /foo\n"); + err = unlink( "/foo" ); + if( err != -EPERM ) SHOW_RESULT( unlink, err ); + + // Verify we cannot rename a read-only file + diag_printf("<INFO>: rename /foo bundy\n"); + err = rename( "/foo", "bundy" ); + if( err != -EPERM ) SHOW_RESULT( rename, err ); + + // Verify we cannot open read-only file for writing + int fd; + diag_printf("<INFO>: create file /foo\n"); + fd = open( "/foo", O_WRONLY ); + if( err != -EPERM ) SHOW_RESULT( rename, err ); + if( err > 0 ) close(fd); + + // Make it Normal + diag_printf("<INFO>: attrib -H /foo\n"); + err = cyg_fs_set_attrib( "/foo", 0 ); + if( err < 0 ) SHOW_RESULT( chmod none , err ); + + // Verify it is now nothing + checkattrib( "/foo", 0 ); + + // Now delete our test file + diag_printf("<INFO>: unlink /foo\n"); + err = unlink( "/foo" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + +#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES + maxfile("file.max"); listdir( "/", true, -1, NULL ); @@ -650,7 +736,6 @@ void fileio1_main( CYG_ADDRESS id ) diag_printf("<INFO>: unlink file.max\n"); err = unlink( "file.max" ); if( err < 0 ) SHOW_RESULT( unlink, err ); - diag_printf("<INFO>: umount /\n"); err = umount( "/" ); if( err < 0 ) SHOW_RESULT( umount, err );
