/*************************************************************************** $RCSfile: ctfilesystem2.h,v $ ------------------- cvs : $Id: ctfilesystem2.h,v 1.5 2003/04/24 01:43:29 aquamaniac Exp $ begin : Fri Aug 09 2002 copyright : (C) 2002 by Martin Preuss email : martin@libchipcard.de *************************************************************************** * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library 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 * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * * MA 02111-1307 USA * * * ***************************************************************************/ #ifndef CTFILESYSTEM2_H #define CTFILESYSTEM2_H #ifdef CT_USE_ENCRYPTION /* FIXME: This is needed for GCC 3.2, because unistd.h and openssl/des.h have * different declarations concerning the exceptions to be thrown * without this you can not compile libchipcard on RedHat 8 systems. */ # define PERL5 # include # undef PERL5 #endif #define CTFILESYSTEM_VERSION_MAJOR 1 #define CTFILESYSTEM_VERSION_MINOR 0 /** * Size of a base block. All other sizes used by the file system are multiple * of this. */ #define CTFILESYSTEM_BASEBLOCKSIZE 32 /** * Maximum capacity this file system supports. Actually this has implications * to the size of the data cache. * The hard limit is 64KB, because the ISO commands for the chipcard do not * allow specifying an offset beyond 64KB. */ #define CTFILESYSTEM_MAXSIZE (64*1024) #define CTFILESYSTEM_FAT_LENGTH 256 #include #include /** * @page cardfspage Card File System 1.0 * @section datorg Data Organisation On The Card * @subsection baseblocks Base Blocks * The memory of the card is divided into base blocks (size is * currently 32 bytes). This is the smallest element that my file system * operates on. The size of everything in this file system is a multiple of * those basic block's size. * * @subsection superblock Super Block * At the beginning of the memory an informational * table describing the file system itself can be found (@ref CTSuperBlock). * * @subsection fat Block Allocation Table * Directly behind this super block is the block allocation table. Others * would call it a FAT (file allocation table). The size of this FAT * is fixed to 256 bytes. Each entry of the FAT is one byte wide and it * corresponds to one data block (the size of a data block * depends on the capacity of the card, but it is a multiple of a basic * block's size). Each entry holds one of the following: *
    *
  • number of the next block in this chain (see below, 0-253)
  • *
  • special value to flag that the end of a chain is reached
  • *
  • special value to flag that this block is free
  • *
  • special value to flag that a block is reserved
  • *
* * When allocating a data block the FAT is scanned for an entry flagging a * free block (see above). If one is found then it will be set with the * special value flagging that this block is the last block of a chain. * When the next block is to be allocated, then additionally the previous * block (which now is not at the end anymore) receives the number of the * following block. The number of the first block is stored in the file's * directory entry, thus creating a block chain.
* The older ones among you may recognize this scheme. * That's the way MSDOS managed floppies and hard discs with their old * FAT (before NTFS or FAT32 came ;-)
* * @subsection dirent Directory Entries * Each file and folder is represented by a special * table (@ref CTDirEntry). This entry holds information about the file or * folder. If a folder contains sub folders, then their entries are stored * within the data area of the parent directory. */ #ifndef DOXYGEN /** * @author Martin Preuss */ class CHIPCARD_API CTBlockMedium: public CTMemoryCard { public: CTBlockMedium(const CTCard &c); virtual ~CTBlockMedium(); virtual CTError readBlocks(int bn, int n, string &bl); virtual CTError writeBlocks(int bn, int n, const string &bl); virtual CTError mountMedium(); virtual CTError unmountMedium(); }; #endif #ifndef DOXYGEN /** * @author Martin Preuss */ class CHIPCARD_API CTCachedBlockMedium: public CTBlockMedium { private: CTDataCache _cache; public: CTCachedBlockMedium(const CTCard &c); virtual ~CTCachedBlockMedium(); virtual CTError readBlocks(int bn, int n, string &bl); virtual CTError writeBlocks(int bn, int n, const string &bl); virtual int flush(int maxb=0x800000) throw (class CTError); virtual void purge(); virtual CTError mountMedium(); virtual CTError unmountMedium(); }; #endif #ifndef DOXYGEN /** * @author Martin Preuss * */ class CHIPCARD_API CTCryptedBlockMedium: public CTCachedBlockMedium { private: des_cblock _desKey1; des_cblock _desKey2; bool _desKeyIsValid; protected: CTError crypt(bool encrypt, const string &src, string &dest); public: CTCryptedBlockMedium(const CTCard &c); virtual ~CTCryptedBlockMedium(); virtual CTError readBlocks(int bn, int n, string &bl, bool cr=false); virtual CTError writeBlocks(int bn, int n, const string &bl, bool cr=false); virtual CTError setPassword(const string &pw); virtual void clearPassword(); }; #endif /* __________________________________________________________________________ * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * CTSuperBlock * YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY */ #define CTFS_SUPERBLOCK_FLAG_CRYPTED 0x0001 #define CTFS_SUPERBLOCK_FLAG_READONLY 0x0002 /** * This class represents a super block and therefore describes the file system * on a card. It contains information such as the used block size, the * capacity of the card and so on. * @author Martin Preuss */ class CHIPCARD_API CTSuperBlock { private: bool _changed; string _mediumName; int _blockSize; int _blocks; int _mediumSize; unsigned char _versionMajor; unsigned char _versionMinor; unsigned int _flags; int _reservedBlocks; int _firstDirBlock; string _userName; CTError _fromString(const string &s); public: /** * @name Constructors and destructors */ //@{ CTSuperBlock(); /** * @internal */ CTSuperBlock(const string &block); /** * @internal */ CTSuperBlock(unsigned int mediumSize); ~CTSuperBlock(); //@} /** * @name General information about the medium */ //@{ /** * Returns the name you assigned to the card. To protect yourself * against acidental data losses you should keeps the names of your * card unique ! */ const string mediumName() const { return _mediumName;}; /** * Returns the capacity of the card. This value does not represent the * capacity for data storage, since the file system occupies a part * of the memory for management purposes. */ int mediumSize() { return _mediumSize;}; /** * Returns the major version of the file system on the card. * The file system library will refuse to mount a medium whose major * version does not math that of the library. */ unsigned char versionMajor() const { return _versionMajor;}; /** * Returns the minor version of the file system on the card. It may * differ from that of the library. * @todo When the minor version of the ard is higher than that of the * library we should mount the medium readonly ! */ unsigned char versionMinor() const { return _versionMinor;}; /** * Tells whether the data on the card is encrypted. */ bool isCrypted() const { return _flags & CTFS_SUPERBLOCK_FLAG_CRYPTED;}; /** * Tells whether the data on the card should be protected against * writing. * @todo I must implement this feature. */ bool isReadOnly() const { return _flags & CTFS_SUPERBLOCK_FLAG_READONLY;}; //@} /** * @name Structural information */ //@{ /** * Returns the size of a data block in bytes. You can use this and the * value of @ref blocks() to determine the for data storage usable * capacity of the card. */ int blockSize() const { return _blockSize;}; /** * Returns the number of data blocks on this card. * You can use this and the value of @ref blockSize() to determine the * for data storage usable capacity of the card. */ int blocks() const { return _blocks;}; //@} /** * @name Internal information * * These methods are not part of the API an may therefore change or even * disappear in future versions. */ //@{ /** * @internal */ int reservedBlocks() const { return _reservedBlocks;}; /** * @internal */ int firstDirBlock() const { return _firstDirBlock;}; /** * @internal */ const string userName() const { return _userName;}; /** * @internal */ bool changed() const { return _changed;}; //@} /** * @name Internal setters */ //@{ /** * @internal */ void setMediumName(const string &n) { _mediumName=n; _changed=true;}; /** * @internal */ void setBlockSize(int n) { _blockSize=n; _changed=true;}; /** * @internal */ void setBlocks(int n) { _blocks=n; _changed=true;}; /** * @internal */ void setReservedBlocks(int i) { _reservedBlocks=i;}; /** * @internal */ void setMediumSize(int n) { _mediumSize=n; _changed=true;}; /** * @internal */ void setVersion(int mj, int mn) { _versionMajor=mj; _versionMinor=mn; _changed=true;}; /** * @internal */ void setIsCrypted(bool b) { if (b) _flags|=CTFS_SUPERBLOCK_FLAG_CRYPTED; else _flags&=~CTFS_SUPERBLOCK_FLAG_CRYPTED; _changed=true;}; /** * @internal */ void setIsReadOnly(bool b) { if (b) _flags|=CTFS_SUPERBLOCK_FLAG_READONLY; else _flags&=~CTFS_SUPERBLOCK_FLAG_READONLY; _changed=true;}; /** * @internal */ void setFirstDirBlock(int i) { _firstDirBlock=i; _changed=true;}; /** * @internal */ void setUserName(const string &n) { _userName=n; _changed=true;}; /** * @internal */ void setChanged(bool b) { _changed=b;}; //@} /** * @name Internal conversion operations */ //@{ /** * @internal */ string toString(); /** * @internal */ string dump(); //@} }; /* __________________________________________________________________________ * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * CTBlockManager * YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY */ #ifndef DOXYGEN /** * @author Martin Preuss * */ class CHIPCARD_API CTBlockManager { private: unsigned char _fat[CTFILESYSTEM_FAT_LENGTH]; int _blocks; bool _changed; public: CTBlockManager(); CTBlockManager(int blocks, const string &fat=""); ~CTBlockManager(); bool changed() const { return _changed;}; void setChanged(bool b) { _changed=b;}; int allocateBlock(int bl=-1); void freeBlock(int bl); void freeChain(int bn); int blocks(int bl=-1); int freeBlocks(); int blockAt(int first, int idx); int nextBlock(int bl); int previousBlock(int bl); int lastBlock(int bl); string toString(); }; #endif // DOXYGEN /* __________________________________________________________________________ * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * CTDataBlockMedium * YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY */ #ifndef DOXYGEN /** * This class operates on data blocks, whose size depends on the size * of the medium. Such a block consists of multiple base blocks. * @author Martin Preuss */ class CHIPCARD_API CTDataBlockMedium: public CTCryptedBlockMedium { friend class CTFileBase; private: int _firstDataBlock; CTSuperBlock _superBlock; CTBlockManager _blockManager; bool _isMounted; CTError _createMedium(unsigned int mediumSize, const string &mediumname, const string &userName, const string &passwd); CTError _readFAT(); CTError _writeFAT(); CTError _readSuperBlock(); CTError _writeSuperBlock(); protected: CTDataBlockMedium(const CTCard &c); public: virtual ~CTDataBlockMedium(); virtual CTError readBlock(int bn, string &bl); virtual CTError writeBlock(int bn, const string &bl); virtual CTError allocateBlock(int &bn); virtual CTError freeBlock(int bn); virtual CTError freeChain(int bn); virtual CTError nextBlock(int &bn); const CTSuperBlock &superBlock() const { return _superBlock;}; virtual int blocks(int bl=-1); virtual int freeBlocks(); virtual int blockAt(int first, int idx); virtual int blockSize() const; virtual int firstDirBlock(); virtual CTError mountMedium(const string &username="", const string &passwd=""); virtual CTError unmountMedium(); virtual CTError createMedium(unsigned int mediumSize, const string &mediumname, const string &userName, const string &passwd); bool isReadOnly() const { return _superBlock.isReadOnly();}; void setReadOnly(bool b) { _superBlock.setIsReadOnly(b);}; virtual int flush(int maxb=0x800000) throw (class CTError); virtual void purge(); }; #endif // DOXYGEN /* __________________________________________________________________________ * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * CTDataFile * YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY */ #ifndef DOXYGEN /** * @author Martin Preuss * */ class CHIPCARD_API CTDataFile { friend class CTDirectoryBase; friend class CTFileBase; private: string _buffer; int _block; int _pos; bool _dirty; bool _valid; int _allocatedSize; int _firstBlock; CTPointer _medium; CTError _readBlock(); CTError _writeBlock(); protected: CTDataFile(); CTDataFile(CTPointer medium, int firstBlock=0); public: ~CTDataFile(); CTError seek(int where); int position(); unsigned char readChar(); string readString(int len); CTError writeChar(unsigned char c); CTError writeString(const string &s); CTError flush(); CTError truncate(); int firstBlock() const { return _firstBlock;}; int blocks(); int allocatedSize(); CTError appendBlock(); }; #endif // DOXYGEN /* __________________________________________________________________________ * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * CTDirEntry * YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY */ /** * This class represents an entry of a folder and therefore describes * a file or directory. The only way to
get an object of this class * which really describes a file is by calling @ref CTFile::statFile * @author Martin Preuss */ class CHIPCARD_API CTDirEntry { private: bool _changed; string _name; unsigned int _attributes; unsigned int _size; int _firstBlock; int _parent; int _indexInParent; CTError _fromString(const string &s); public: /** * Attributes of a file or folder. */ enum Attributes { /** * Entry is in use */ Attr_USED =0x0001, /** * Reading the file/folder is allowed */ Attr_READ =0x0002, /** * Writing to the file/folder is allowed. */ Attr_WRITE =0x0004, /** * Entry is a directory */ Attr_DIR =0x0008, /** * Entry is hidden (this attribure is currently unused) */ Attr_HIDDEN=0x0010 }; /** * @name Constructors and destructors * * The only constructor you will be confronted with is that without * arguments, since you will rarely need create a valid direntry yourself. */ //@{ /** * This is the only constructor interesting for application developers. */ CTDirEntry(); /** * @internal */ CTDirEntry(int parent, const string &name, unsigned int attribs=Attr_USED, unsigned int size=0, int firstblock=-1); /** * @internal */ CTDirEntry(const string &s); /** * @internal */ CTDirEntry(int parent, int indexInParent=-1); ~CTDirEntry(); //@} /** * @name Retrieving information about this file or directory */ //@{ /** * Returns the name of this file or directory. * @author Martin Preuss */ const string &name() const { return _name;}; /** * Returns the attributes of this file or directory (@ref Attributes) * @author Martin Preuss */ unsigned int attributes() const { return _attributes;}; /** * Size of this file. If this entry describes a directory then it's * is zero. * @author Martin Preuss */ int size() const { return _size;}; //@} /** * @name Retrieving internal information * * The members returned here are internal and not part of the API, * so you should not expect them to be unchanged in future versions ! */ //@{ /** * Was this entry changed since last read/write ? * @author Martin Preuss */ bool changed() const { return _changed;}; /** * Returns the number of the first block of this file. * @author Martin Preuss */ int firstBlock() const { return _firstBlock;}; /** * This is the first block of the parent. This can be used to scan * the parent for entries. The parent is the folder where this entry * is contained. * @author Martin Preuss */ int parent() const { return _parent;}; /** * This is the position within the parent folder where this entry is * contained. If -1 then this entry is a new one and has not been stored * yet. * @author Martin Preuss */ int indexInParent() const { return _indexInParent;}; //@} /** * @name Internal setters */ //@{ /** * @internal */ void setAttributes(unsigned int i) { _attributes=i; _changed=true;}; /** * @internal */ void setSize(unsigned int i) { _size=i; _changed=true;}; /** * @internal */ void setName(const string &s) { _name=s; _changed=true;}; /** * @internal */ void setFirstBlock(int i) { _firstBlock=i; _changed=true;}; /** * @internal */ void setParent(int i) { _parent=i; _changed=true;}; /** * @internal */ void setIndexInParent(int i) { _indexInParent=i;}; /** * @internal */ void setChanged(bool b) { _changed=b;}; //@} /** * @name Internal Conversion operations */ //@{ /** * @internal */ string toString(); /** * @internal */ string dump(); //@} }; #ifndef DOXYGEN /** * * @author Martin Preuss */ class CHIPCARD_API CTDirectoryBase: public CTDataFile { private: CTDirEntry _entry; int _currEntry; CTError _readEntry(CTDirEntry &de, int idx); int _findFreeEntry(); int _findOrAddFreeEntry(); public: CTDirectoryBase(); CTDirectoryBase(CTPointer medium, int firstBlock=0); ~CTDirectoryBase(); CTError firstEntry(CTDirEntry &de); CTError nextEntry(CTDirEntry &de); CTDirEntry findEntry(const string &name); /** * Writes the given entry to the medium. * If the entries indexInParent() is valid then it will be used to * determine where to save this entry. Otherwise a new entry will * created on the medium and the indexInParent field will be updated. */ CTError writeEntry(CTDirEntry &de); }; #endif #ifndef DOXYGEN /** * @author Martin Preuss * */ class CHIPCARD_API CTFileBase { friend class CTFile; friend class CTDirectory; private: CTPointer _medium; string _path; CTDirEntry _entry; bool _isOpen; CTDataFile _data; string _normalizeName(string n); CTError _createEntry(const string &n, unsigned int attribs, CTDirEntry &fileEntry); protected: const CTDirEntry &dirEntry() const { return _entry;}; CTDirEntry path2Entry(const string &path); CTError writeEntry(CTDirEntry &entry); CTFileBase(); public: CTFileBase(CTPointer medium, const string &path); virtual ~CTFileBase(); bool isOpen() const { return _isOpen;}; virtual CTError openFile(); virtual CTError closeFile(); virtual CTError createFile(unsigned int attribs= CTDirEntry::Attr_USED | CTDirEntry::Attr_READ | CTDirEntry::Attr_WRITE); virtual CTError removeFile(); virtual CTError statFile(CTDirEntry &ent); CTError renameFile(const string &n); CTError truncate(); CTError seek(int where); int position(); int size(); unsigned char readChar(); string readString(int len); CTError writeChar(unsigned char c); CTError writeString(const string &s); CTError flush(); }; #endif // DOXYGEN /** * This class provides a file system on memory cards. If you want to access * files and/or directories on such a file system you need the classes * @ref CTFile and @ref CTDirectory.
* For information about the Card File System itself please go to * @ref cardfspage * @author Martin Preuss * @ingroup llcardfs * @short Provides a file system on memory cards */ class CHIPCARD_API CTCardFS: public CTDataBlockMedium { private: public: /** * @name Constructors/Destructors */ //@{ /** * This constructor is mainly used by derived classes to transform * a basic CTCard object to a more special one. This allows opening a * card as a CTCard object and then create e.g. a CTMemoryCard from * this one. The source card will be immediately closed. The only thing * you should do with it is to delete it. You should NOT use it any * longer !! * @param c reference to the CTCard object to be transformed * @author Martin Preuss */ CTCardFS(const CTCard &c); virtual ~CTCardFS(); //@} /** * @name Mounting and creating * * These methods allow mounting/unmounting and formatting of a memory * card. Mounting the card means to connect to the card thus making * it's content available. Upon mount all information necessary to * manage the medium is read from the card. */ //@{ /** * Connects the card and reads all information needed to manage the * file system on it (CTSuperBlock, the FAT). * If neither username nor passwd are given (or either one is empty) * then no encryption is assumed. However, the file system stores a flag * on the card (in the CTSuperBlock) to determine whether the data is * encrypted and refuses to mount when in the case of missing username * or password. This does not protect against reading raw data bytes * from the card but it prevents this class from accidentally * corrupting your data (in case of wrong or missing password). * @author Martin Preuss * @return error object (call isOk() on it to see if there was an error) * @param username name of the owner of the card. This name is given * upon creation of the file system on the card and cannot be altered. * @param passwd the password used for en-/decryption. */ virtual CTError mountMedium(const string &username="", const string &passwd=""); /** * Unmounts the file system thus disconnecting the card physically. * Before disconnecting the cache is flushed. * @author Martin Preuss * @return error object (call isOk() on it to see if there was an error) */ virtual CTError unmountMedium() { return CTDataBlockMedium::unmountMedium();}; /** * Format a memory card for use by the Card File System. * This method will create and write all data needed to manage a file * system on it. If username and password are given then all * data will be encrypted. If either of them is missing, then the * card will not be in crypto mode (not recommended)
* Note: This method does not leave the medium mounted ! * @author Martin Preuss * @param mediumSize capacity of the card in bytes * @param mediumName assigns a name to the medium (up to 16 chars) * @param userName used for encryption, see introduction * @param passwd used for encryption */ virtual CTError createMedium(unsigned int mediumSize, const string &mediumName, const string &userName, const string &passwd); //@} /** * @name Information about the medium * * These method tell about the size of the medium, the number of * free blocks etc. They do only work if the medium is mounted. */ //@{ /** * All data of the file system is organized in data blocks. The size * of such a block depends on the capacity of your memory card. * @return number of blocks on this card * @author Martin Preuss */ virtual int blocks() { return CTDataBlockMedium::blocks(-1);}; /** * This method tells you how many unused blocks there are. This method * and @ref blockSize() will help you to determine the number of * free bytes on the card. * @return number of unused blocks * @author Martin Preuss */ virtual int freeBlocks() { return CTDataBlockMedium::freeBlocks();}; /** * This method returns the size of a data block. This size depends on * the capacity of your card. It is computed this way: * *
   *
   * int i;
   * int p;
   * int l;
   * int datasize;
   *
   * // calculate data size
   * // number of base blocks for superblock
   * p=CTFS_SUPERBLOCK_LENGTH/CTFILESYSTEM_BASEBLOCKSIZE;
   * if (CTFS_SUPERBLOCK_LENGTH % CTFILESYSTEM_BASEBLOCKSIZE)
   * p++;
   *
   * // calculate number of base blocks for FAT
   * l=CTFILESYSTEM_FAT_LENGTH/CTFILESYSTEM_BASEBLOCKSIZE;
   * if (CTFILESYSTEM_FAT_LENGTH % CTFILESYSTEM_BASEBLOCKSIZE)
   * l++;
   *
   * datasize=mediumsize-((p+l)*CTFILESYSTEM_BASEBLOCKSIZE);
   *
   * // calculate appropriate block size
   * _blockSize=datasize/253;
   * // size smaller than base block size ?
   * if (_blockSize
   * @author Martin Preuss
   * @return block size in bytes
   */
  virtual int blockSize() const { return CTDataBlockMedium::blockSize();};

  /**
   * The super block consists of the first blocks of the medium. It is
   * never encrypted (except the userName, which is encrypted).
   * This block holds some basic facts about the medium. Please refer
   * to @ref CTSuperBlock. The medium must already be mounted !
   * @author Martin Preuss
   * @return const reference to the superblock of this medium.
   */
  const CTSuperBlock &superBlock() const {
    return CTDataBlockMedium::superBlock();};

  /**
   * Currently this flag is ignored by libcardfs, but maybe later I will
   * implement a write protection.
   * @author Martin Preuss
   * @return true if the medium is write protected
   */
  bool isReadOnly() const { return CTDataBlockMedium::isReadOnly();};

  /**
   * Currently this flag is ignored by libcardfs, but maybe later I will
   * implement a write protection.
   * @author Martin Preuss
   * @param b true if the medium shall be write protected
   */
  void setReadOnly(bool b) { CTDataBlockMedium::setReadOnly(b);};
  //@}

  /**
   * @name Cache Management
   *
   * These methods allow flushing and invalidating the data cache.
   * This cache holds all data blocks of the card that have been read or
   * written. The cache holds the data blocks as they are on the card,
   * so when using encryption the cache will only hold encrypted blocks.
   * This way the cache mechanism does not corrupt the security.
   */
  //@{
  /**
   * Flushes the cache. This means that all unwritten data will be
   * written to the card. This method should be called every once in a
   * while (as the CardFS daemon does) to protect your data against
   * getting lost (maybe due to a failure in one of the programs using
   * the Card File System).
   * @author Martin Preuss
   * @return number of blocks flushed (0 if none, -1 on error)
   * @param maxb number of blocks to flush. Flushing the whole cache
   * can take up to a minute or even longer, so if you just want to
   * flush some blocks of the cache (like the CardFS daemon) without
   * being busy and unresponsive for such a long time you can give the
   * number of blocks to write (8 is a fair value). However, when omitted
   * this number defaults to a value high enough to flush all
   * blocks.
   */
  virtual int flush(int maxb=0x800000) throw (class CTError) {
    return CTDataBlockMedium::flush(maxb);};

  /**
   * Invalidate the cache. You should call this prior to unmounting the
   * card if you don't want to committ changes to the card (Please
   * remember that @ref unmountMedium will flush the cache !)
   * @author Martin Preuss
   */
  virtual void purge() { CTDataBlockMedium::purge();};
  //@}
};



/**
 * @author Martin Preuss
 * @ingroup llcardfs
 */
class CHIPCARD_API CTFile: private CTFileBase {
    CTFileBase _fb;

public:
    /**
     * @name Constructors and destructors
     */
    //@{

    CTFile();

    /**
     * @author Martin Preuss
     * @param medium CTPointer to the medium this file belongs to (card)
     * @param path path of the file
     */
    CTFile(CTPointer medium,
           const string &path);
    ~CTFile();
    //@}

    /**
     * @name Opening, creating and closing operations
     *
     * Guess what these methods do...
* Some operations need the file to be open. */ //@{ /** * Opens a file. It must exist. * @author Martin Preuss */ CTError openFile() { return CTFileBase::openFile();}; /** * Close a file that has been opened or created. There is no * nest counter, if the file is not open an error will be returned. * @author Martin Preuss */ CTError closeFile() { return CTFileBase::closeFile();}; /** * Creates a file using the given attributes. If a file with that * name already exists an error will be returned. * @author Martin Preuss */ CTError createFile(unsigned int attribs= CTDirEntry::Attr_USED | CTDirEntry::Attr_READ | CTDirEntry::Attr_WRITE){ return CTFileBase::createFile(attribs|CTDirEntry::Attr_USED); }; //@} /** * @name Renaming, removing, truncating or stating a file * * These operations perform with the file beeing either open or closed * (except removeFile, it needs the file to be closed). */ //@{ /** * Removes the file. If it does not exist anyway then an error will * be returned. The file must not be open.. * @author Martin Preuss */ CTError removeFile() { return CTFileBase::removeFile();}; /** * Renames this file. This may move this file to a different folder. * The file may be open. * @author Martin Preuss * @param n new name */ CTError renameFile(const string &n) { return CTFileBase::renameFile(n);}; /** * Collects some information about the file. The file may be open or * closed. * @author Martin Preuss * @param ent reference to a CTDirEntry object to receive the info */ CTError statFile(CTDirEntry &ent) { return CTFileBase::statFile(ent);}; /** * Truncates file to zero. * @author Martin Preuss */ CTError truncateFile() { return CTFileBase::truncate();};; //@} /** * @name Seeking operations * * These methods deal with the current position within the file. * Obviously it needs to be open for these methods to perform. */ //@{ /** * Seeks to the given position. If the position is beyond the end of * this file no error is returned ! If a write follwos then the file * will grow to fit the size indicated by the file position. An * immediate read request however will fail * @author Martin Preuss * @param where position to seek */ CTError seek(int where) { return CTFileBase::seek(where);}; /** * Returns the current position of the file pointer. * @author Martin Preuss * @return current position in the file */ int position() { return CTFileBase::position();}; //@} /** * @name Reading and writing * * The following methods allow reading and writing data to/from a * file and advance the file pointer. The file needs to be open. */ //@{ /** * Read the next character out of the file. If the file pointers show * beyond the file's end an error will be thrown. * @author Martin Preuss */ unsigned char readChar() { return CTFileBase::readChar();}; /** * Reads the next bytes up to the given length. * Calls @ref readChar(). * @author Martin Preuss * @param len limit for the number of bytes to read */ string readString(int len); /** * Writes a character to the current position in the file and * advances the file pointer. If the write position is beyond the * end of file an appropriate number of blocks will be allocated * for this file and assigned to it. * @author Martin Preuss */ CTError writeChar(unsigned char c) { return CTFileBase::writeChar(c);}; /** * Writes a string of data to this file. Calls @ref writeChar(). * @author Martin Preuss */ CTError writeString(const string &s) {return CTFileBase::writeString(s);}; /** * Flushes this file, which means all unwritten data will be written * to the medium. Well, it will rather be written to the cache of * the file system. * @author Martin Preuss */ CTError flush() { return CTFileBase::flush();}; //@} }; /** * This class represents a directory. * @author Martin Preuss * @ingroup llcardfs */ class CHIPCARD_API CTDirectory: private CTFileBase { public: CTDirectory(); CTDirectory(CTPointer medium, const string &path); ~CTDirectory(); CTError openDirectory(); CTError closeDirectory() { return CTFileBase::closeFile();}; CTError createDirectory(unsigned int attribs= CTDirEntry::Attr_USED | CTDirEntry::Attr_READ | CTDirEntry::Attr_WRITE){ return CTFileBase::createFile(attribs|CTDirEntry::Attr_DIR); }; CTError removeDirectory(); CTError renameDirectory(const string &n) { return CTFileBase::renameFile(n); }; CTError firstEntry(CTDirEntry &de); CTError nextEntry(CTDirEntry &de); CTError entry(CTDirEntry &de,int idx); }; #endif