Overview | Package | Class | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## opencard.opt.iso.fs
Interface FileAccessCardService

All Known Subinterfaces:
  FileSystemCardService

public abstract interface FileAccessCardService
extends CardServiceInterface, SecureService

Interface to a card service for ISO 7816-4 file access functionality. This service provides read and write access to transparent as well as to structured files. In addition, there are methods to check whether a file exists and to access information stored in a file header. Both methods can be mapped onto the ISO-specified SELECT command.
This is a low-level interface that requires careful programming when used directly. Especially the `CardFilePath` objects used for identifying files on the smartcard are somehow tricky, as described below. Higher level access is provided by classes like `CardFile`, `CardFileInputStream`, `CardFileOutputStream`, `CardRandomByteAccess`, or `CardRandomRecordAccess`. They can be created on top of a `FileAccessCardService`. The rest of this comment specifies the conditions that have to be satisfied if this interface is implemented or used directly.

`CardFilePath` objects, which are used as arguments in almost all methods, are mutable. Since they are first class candidates for keys in hashtables, there are some conditions that must be satisfied by applications as well as by card services. For the card service side, there are two restrictions:

1. A path given as an argument must not be modified by the service. If modifications to the path are necessary, it has to be copied, and the copy can be modified. Therefore, an application can rely on the path to be the same before and after an invocation of a card service method.
2. A path given as an argument may be modified by the application after the invoked card service method returned. If a card service needs to store a path across invocations, for example for caching purposes, the path has to be copied and the copy can be stored. Therefore, an application is allowed to modify a path, regardless of whether it has been used as an argument to a card service or not.

The restrictions imposed on applications are more complex. However, these are common sense restrictions that will typically be satisfied by any reasonable application program. As a rule of thumb, path supplied as arguments must be as simple as possible, but not simpler. These kind of paths are referred to as canonical paths.

1. A path given as an argument to a card service must be absolute. If the path consists only of file ids and short file ids, the first component of the path must be the id of the master file (MF). A path to the MF can be obtained by invoking `getRoot`. This path can then be copied and extended.
   A path that contains an application identifier is implicitly absolute, since application identifiers are supported only as the first component in a path. Hierarchical applications are not supported by OCF, even if a smartcard does. There may be additional restrictions imposed on the layout of smartcards to enforce a correct behavior of card services.
   This restriction guarantees to the card service that selection of the full path will select the correct file on the smartcard, no matter what file has been selected before.
2. A path given as an argument to a card service must be straight. It is not allowed for a path to switch to parent directories, even if the smartcard would support this feature. It is also unacceptable to include the master file in a path, unless it is the first component.
   This restriction almost guarantees to the card service that any file on the smartcard is identified by a unique path. The path can therefore be used as a key in hashtables or other dictionaries that store information related to a file. It is also possible to cut off the leading components of a path if the path to the currently selected directory (DF) is a prefix of the path to select. Besides, this restriction reduces memory consumption and speeds up operations.
3. If a file on the smartcard is referenced by a path with an application name, it should not be referenced by another path without application name. Together with the preceeding restriction, this basically means: a file on the smartcard should be referenced by a unique identifier. The reason for this has been mentioned in the preceeding restriction.
   In this last restriction, the term should is used instead of must. This is because an application programmer cannot know about the potential programmers of other applications that refer to the same file on the card. One could decide to use a path with an application name, while another one could decide to use a path with file ids only.
   In this case, if both applications run simultaneously, and the card services created for them use a shared data structure like a file cache, the same file may be referenced by two different paths. This could lead to inconsistencies in the shared data, for example if one of the applications deletes the file. However, this case is too unlikely to worry about.
   If different card services, or different instances of one card service, use the same smartcard without cooperating on shared data, inconsistencies in cached data cannot be avoided at all, no matter what restrictions are put on path names.

See Also:
  `getRoot()`, `CardFilePath`, `CardFile`, `CardFileInputStream`, `CardFileOutputStream`, `CardRandomByteAccess`, `CardRandomRecordAccess`

Field Summary
`static int` | `READ_SEVERAL` Magic number for `read` and `readRecords`.

Method Summary
`void` | `appendRecord(CardFilePath file, byte[] data)` Appends data to a structured file.
`boolean` | `exists(CardFilePath file)` Checks whether a file exists.
`CardFileInfo` | `getFileInfo(CardFilePath file)` Queries information about a file.
`CardFilePath` | `getRoot()` Returns the absolute path to the master file (MF) of the smartcard.
`byte[]` | `read(CardFilePath file, int offset, int length)` Reads a given amount of data from a transparent file.
`byte[]` | `readRecord(CardFilePath file, int recordNumber)` Reads a record from a structured file.
`byte[][]` | `readRecords(CardFilePath file, int number)` Reads consecutive records from a structured file.
`void` | `write(CardFilePath file, int offset, byte[] data)` Writes data to a transparent file, using a complete array.
`void` | `write(CardFilePath file, int foffset, byte[] source, int soffset, int length)` Writes data to a transparent file, using part of an array.
`void` | `writeRecord(CardFilePath file, int recordNumber, byte[] data)` Writes data to a structured file.

Methods inherited from interface opencard.opt.service.CardServiceInterface
`getCard, setCHVDialog`

Methods inherited from interface opencard.opt.security.SecureService
`provideCredentials`

Field Detail

### READ_SEVERAL

    public static final int READ_SEVERAL

  Magic number for `read` and `readRecords`. This constant can be passed as the `length` argument to the `read` method, if an unspecified number of bytes should be read. It can also be passed as the `number` argument to `readRecords`, to read all records in a structured file.
  See Also:
    `read(opencard.opt.iso.fs.CardFilePath, int, int)`, `readRecords(opencard.opt.iso.fs.CardFilePath, int)`

Method Detail

### getRoot

    public CardFilePath getRoot()

  Returns the absolute path to the master file (MF) of the smartcard. For ISO compliant cards, the master file has the fixed id 0x3f00, so this method will typically be implemented in the following way:

       private final static CardFilePath master_file
                      = new CardFilePath(":3f00");

       public final CardFilePath getRoot()
       {
         return master_file;
       }

  The value returned is not allowed to be modified. When taking a look at the sample implementation above, it should be obvious why. There are no exceptions thrown by this method, since it does not require interaction with the smartcard.

  Returns:
    the path to the master file

### exists

    public boolean exists(CardFilePath file)
                   throws opencard.core.service.CardServiceException,
                          opencard.core.terminal.CardTerminalException

  Checks whether a file exists.
  Parameters:
    `file` - the path to the file to query
  Returns:
    `true` if the file exists, `false` otherwise
  Throws:
    opencard.core.service.CardServiceException - if the service encountered an error
    opencard.core.terminal.CardTerminalException - if the terminal encountered an error

### getFileInfo

    public CardFileInfo getFileInfo(CardFilePath file)
                             throws opencard.core.service.CardServiceException,
                                    opencard.core.terminal.CardTerminalException

  Queries information about a file.
  Parameters:
    `file` - the path to the file to query
  Returns:
    information about the file, or `null` if it doesn't exist
  Throws:
    opencard.core.service.CardServiceException - if the service encountered an error
    opencard.core.terminal.CardTerminalException - if the terminal encountered an error

### read

    public byte[] read(CardFilePath file,
                       int offset,
                       int length)
                throws opencard.core.service.CardServiceException,
                       opencard.core.terminal.CardTerminalException

  Reads a given amount of data from a transparent file. Transparent files are similiar to files in traditional file systems. They provide random access to an array of bytes.
  Instead of specifying a number of bytes to read, the constant `READ_SEVERAL` can be passed. The service will then read at least one byte, probably more. Only one read command will be sent to the card in this case, that means a maximum of about 255 bytes can be returned. If the specified `offset` points to the end of the file, that is if not even one byte can be read, `null` is returned, but no exception will be thrown.
  Parameters:
    `file` - the path to the file to read from
    `offset` - the index of the first byte to read (0 for first)
    `length` - the number of bytes to read, or `READ_SEVERAL`. If 0 is passed, the behavior is implementation dependent.
  Returns:
    an array holding the data read from the file, or `null` if a read with length `READ_SEVERAL` has been performed at the end of the file
  Throws:
    opencard.core.service.CardServiceException - if the service encountered an error
    opencard.core.terminal.CardTerminalException - if the terminal encountered an error
  See Also:
    `READ_SEVERAL`

### readRecord

    public byte[] readRecord(CardFilePath file,
                             int recordNumber)
                      throws opencard.core.service.CardServiceException,
                             opencard.core.terminal.CardTerminalException

  Reads a record from a structured file. Structured files consist of records. Each record is an array of bytes. Data is addressed only in terms of records, and records are always read completely. The record size will be determined by the card service. ISO 7816-4 specifies the following structured file types:

  linear fixed
    An array of records, with absolute addressing. All records have the same, fixed size.
  linear variable
    An array of records, with absolute addressing. Every record may have a different size.
  cyclic fixed
    A ring buffer of records, with relative addressing. All records have the same, fixed size. Cyclic files are typically used for keeping logs on transactions.

  Files with a cyclic structure may not be easily accessible with this method, since the absolute addressing may be interpreted in different ways by different cards. For example, the first record may be the record that is physically stored first on the card, or it may be the record that was last written into the ring buffer. The method `readRecords` is the preferred way to read cyclic files.

  Parameters:
    `file` - the path to the file to read from
    `record` - the index of the record to read (0 for first)
  Returns:
    an array holding the record read. If the record has length 0, which may happen with linear variable files, an array of length 0 is returned.
  Throws:
    opencard.core.service.CardServiceException - if the service encountered an error
    opencard.core.terminal.CardTerminalException - if the terminal encountered an error
  See Also:
    `readRecords(opencard.opt.iso.fs.CardFilePath, int)`

### readRecords

    public byte[][] readRecords(CardFilePath file,
                                int number)
                         throws opencard.core.service.CardServiceException,
                                opencard.core.terminal.CardTerminalException

  Reads consecutive records from a structured file. For a discussion of structured file types, see `readRecord`. The first record read will always be the first in the structured file. For linear files with fixed or variable record size, first is interpreted as an absolute record number. For cyclic files, first refers to the record most recently written. Starting with that first record, the specified number of consecutive records will be read. In the case of a cyclic file, the second record will be the second most recently written record, and so on.
  Typically, smartcards will implement absolute addressing for cyclic files, where the first record is the least recently written, and the following are sorted by decreasing time of writing. In this case, this method can be implemented by repeated invocations of `readRecord`.
  The magic number `READ_SEVERAL` may be passed as the number of records to read. In this case, all records in the file are read. This is especially useful with linear variable files, where the number of records in the file cannot be determined via file attributes.
  Parameters:
    `file` - the path to the file to read from
    `number` - the number of records to read, or `READ_SEVERAL`. If 0 is passed, the behavior is implementation dependent.
  Returns:
    an array holding the records read, where the records are arrays themselves
  Throws:
    opencard.core.service.CardServiceException - if the service encountered an error
    opencard.core.terminal.CardTerminalException - if the terminal encountered an error
  See Also:
    `readRecord(opencard.opt.iso.fs.CardFilePath, int)`, `READ_SEVERAL`

### write

    public void write(CardFilePath file,
                      int foffset,
                      byte[] source,
                      int soffset,
                      int length)
               throws opencard.core.service.CardServiceException,
                      opencard.core.terminal.CardTerminalException

  Writes data to a transparent file, using part of an array. This method corresponds to the UPDATE BINARY command defined in ISO 7816-4. The term `write` has been chosen since it is more natural for programmers that are used to traditional file systems. For an explanation of the term transparent file, see `read`. To write an array completely, the convenience method `write` with three arguments can be used.
  Parameters:
    `file` - the path to the file to write to
    `foffset` - the file index of the first byte to overwrite (0 for first byte in file)
    `source` - an array holding the data to write
    `soffset` - the array index of the first byte to write
    `length` - the number of bytes to write
  Throws:
    opencard.core.service.CardServiceException - if the service encountered an error
    opencard.core.terminal.CardTerminalException - if the terminal encountered an error
  See Also:
    `read(opencard.opt.iso.fs.CardFilePath, int, int)`, `write(opencard.opt.iso.fs.CardFilePath, int, byte[])`

### write

    public void write(CardFilePath file,
                      int offset,
                      byte[] data)
               throws opencard.core.service.CardServiceException,
                      opencard.core.terminal.CardTerminalException

  Writes data to a transparent file, using a complete array. This is a convenience method for `write` with five arguments. It does not allow to specify an array index and the number of bytes to write. Instead, it always writes the complete array passed. Typically, this method will be implemented as follows:

       final public void write(CardFilePath file, int offset, byte[] data)
        {
          write(file, offset, data, 0, data.length);
        }

  Parameters:
    `file` - the path to the file to write to
    `offset` - the file index of the first byte to overwrite (0 for first byte in file)
    `data` - the data to write to the file
  Throws:
    opencard.core.service.CardServiceException - if the service encountered an error
    opencard.core.terminal.CardTerminalException - if the terminal encountered an error
  See Also:
    `write(opencard.opt.iso.fs.CardFilePath, int, byte[], int, int)`

### writeRecord

    public void writeRecord(CardFilePath file,
                            int recordNumber,
                            byte[] data)
                     throws opencard.core.service.CardServiceException,
                            opencard.core.terminal.CardTerminalException

  Writes data to a structured file. This method corresponds to the UPDATE RECORD command defined in ISO 7816-4. The term `write` has been chosen since it is more natural for programmers that are used to traditional file systems. For a discussion of structured file types, see `readRecord`.
  A record is always written completely. For linear fixed files, the size of the input record must be exactly the file's record size. For files with variable record sizes, the size of the input record must not exceed the maximum size for the record that will be overwritten. That maximum size is typically the initial size of the record when the smartcard was initialized. For cyclic files, this method is not necessarily supported. Use `appendRecord` instead.
  Parameters:
    `file` - the path to the file to write to
    `record` - the index of the record to overwrite (0 for first)
    `data` - the data to write to the file
  Throws:
    opencard.core.service.CardServiceException - if the service encountered an error
    opencard.core.terminal.CardTerminalException - if the terminal encountered an error
  See Also:
    `readRecord(opencard.opt.iso.fs.CardFilePath, int)`, `appendRecord(opencard.opt.iso.fs.CardFilePath, byte[])`

### appendRecord

    public void appendRecord(CardFilePath file,
                             byte[] data)
                      throws opencard.core.service.CardServiceException,
                             opencard.core.terminal.CardTerminalException

  Appends data to a structured file. For a discussion of structured file types, see `readRecord`. For linear files with variable record size, this method appends a new record at the end of the file. Typically, the space for appending a record must have been allocated at the time the file was created. For cyclic files, this method overwrites the oldest record in the ring buffer, which then becomes the newest. The size of the record to append has to match the file's record size exactly. For linear files with a fixed record size, this method is not necessarily supported. Use `writeRecord` instead.
  Parameters:
    `file` - the path to the file to append to
    `data` - the data to write to the new record
  Throws:
    opencard.core.service.CardServiceException - if the service encountered an error
    opencard.core.terminal.CardTerminalException - if the terminal encountered an error
  See Also:
    `readRecord(opencard.opt.iso.fs.CardFilePath, int)`, `writeRecord(opencard.opt.iso.fs.CardFilePath, int, byte[])`

Overview | Package | Class | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD