opencard.opt.iso.fs
Interface FileAccessCardService
- All Superinterfaces:
- CardServiceInterface, SecureService
- All Known Subinterfaces:
- FileSystemCardService, IsoFileSystemCardService
- All Known Implementing Classes:
- ACOSCardService, GemXCosCardService, IsoCardService
public 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:
- 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.
- 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.
- 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.
- 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.
- 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.
- Version:
- $Id: FileAccessCardService.java,v 1.1.1.1 1999/10/05 15:08:47 damke Exp $
- Author:
- Roland Weber (rolweber@de.ibm.com)
- 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. |
READ_SEVERAL
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)
,
Constant Field Values
getRoot
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
boolean exists(CardFilePath file)
throws CardServiceException,
CardTerminalException
- Checks whether a file exists.
- Parameters:
file
- the path to the file to query
- Returns:
- true if the file exists, false otherwise
- Throws:
CardServiceException
- if the service encountered an error
CardTerminalException
- if the terminal encountered an error
getFileInfo
CardFileInfo getFileInfo(CardFilePath file)
throws CardServiceException,
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:
CardServiceException
- if the service encountered an error
CardTerminalException
- if the terminal encountered an error
read
byte[] read(CardFilePath file,
int offset,
int length)
throws CardServiceException,
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 fromoffset
- 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:
CardServiceException
- if the service encountered an error
CardTerminalException
- if the terminal encountered an error- See Also:
READ_SEVERAL
readRecord
byte[] readRecord(CardFilePath file,
int recordNumber)
throws CardServiceException,
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 fromrecordNumber
- 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:
CardServiceException
- if the service encountered an error
CardTerminalException
- if the terminal encountered an error- See Also:
readRecords(opencard.opt.iso.fs.CardFilePath, int)
readRecords
byte[][] readRecords(CardFilePath file,
int number)
throws CardServiceException,
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 fromnumber
- 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:
CardServiceException
- if the service encountered an error
CardTerminalException
- if the terminal encountered an error- See Also:
readRecord(opencard.opt.iso.fs.CardFilePath, int)
,
READ_SEVERAL
write
void write(CardFilePath file,
int foffset,
byte[] source,
int soffset,
int length)
throws CardServiceException,
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 tofoffset
- the file index of the first byte to overwrite
(0 for first byte in file)source
- an array holding the data to writesoffset
- the array index of the first byte to writelength
- the number of bytes to write
- Throws:
CardServiceException
- if the service encountered an error
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
void write(CardFilePath file,
int offset,
byte[] data)
throws CardServiceException,
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 tooffset
- the file index of the first byte to overwrite
(0 for first byte in file)data
- the data to write to the file
- Throws:
CardServiceException
- if the service encountered an error
CardTerminalException
- if the terminal encountered an error- See Also:
write(opencard.opt.iso.fs.CardFilePath, int, byte[], int, int)
writeRecord
void writeRecord(CardFilePath file,
int recordNumber,
byte[] data)
throws CardServiceException,
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 torecordNumber
- the index of the record to overwrite (0 for first)data
- the data to write to the file
- Throws:
CardServiceException
- if the service encountered an error
CardTerminalException
- if the terminal encountered an error- See Also:
readRecord(opencard.opt.iso.fs.CardFilePath, int)
,
appendRecord(opencard.opt.iso.fs.CardFilePath, byte[])
appendRecord
void appendRecord(CardFilePath file,
byte[] data)
throws CardServiceException,
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 todata
- the data to write to the new record
- Throws:
CardServiceException
- if the service encountered an error
CardTerminalException
- if the terminal encountered an error- See Also:
readRecord(opencard.opt.iso.fs.CardFilePath, int)
,
writeRecord(opencard.opt.iso.fs.CardFilePath, int, byte[])