Implementation of the file system device type. More...
#include "skinkit.h"
#include "devutils.h"
#include "ripthread.h"
#include "file.h"
#include "paths.h"
#include "mem.h"
#include "sync.h"
#include "skindevs.h"
#include "hqmemcpy.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include "swdevice.h"
#include "swoften.h"
Data Structures | |
struct | FileDeviceState |
Structure to hold device-specific state. More... | |
Typedefs | |
typedef struct FileDeviceState | FileDeviceState |
Structure to hold device-specific state. | |
Functions | |
FileDeviceState * | devstate (DEVICELIST *dev) |
Extract private state from devicelist. | |
static HqBool | initialiseDeviceState (DEVICELIST *dev) |
Initialise a FileDeviceState object. More... | |
static void | uninitialiseDeviceState (FileDeviceState *pDeviceState) |
Uninitialise a FileDeviceState object. | |
static int32 | fs_device_init (DEVICELIST *dev) |
File system device initialisation. More... | |
static int32 | fs_ioerror (DEVICELIST *dev) |
static int32 | fs_spare (void) |
static DEVICE_FILEDESCRIPTOR | fs_open_file (DEVICELIST *dev, uint8 *filename, int32 openflags) |
The file_open call for the file system device type. | |
static int32 | fs_read_file (DEVICELIST *dev, DEVICE_FILEDESCRIPTOR descriptor, uint8 *buff, int32 len) |
The read_file routine for the file system device type. More... | |
static int32 | fs_write_file (DEVICELIST *dev, DEVICE_FILEDESCRIPTOR descriptor, uint8 *buff, int32 len) |
The write_file routine for the file system device type. More... | |
static int32 | fs_close_file (DEVICELIST *dev, DEVICE_FILEDESCRIPTOR descriptor) |
The close_file routine for the file system device type. More... | |
static int32 | fs_seek_file (DEVICELIST *dev, DEVICE_FILEDESCRIPTOR descriptor, Hq32x2 *destination, int32 flags) |
The seek_file routine for the file system device type. | |
static int32 | fs_bytes_file (DEVICELIST *dev, DEVICE_FILEDESCRIPTOR descriptor, Hq32x2 *bytes, int32 reason) |
The bytes_file routine for the file system device type. More... | |
static int32 | fs_status_file (DEVICELIST *dev, uint8 *filename, STAT *statbuff) |
The status_file routine for the file system device type. | |
static void * | fs_start_file_list (DEVICELIST *dev, uint8 *pattern) |
| |
static int32 | fs_next_file (DEVICELIST *dev, void **handle, uint8 *pattern, FILEENTRY *entry) |
fs_next_file | |
static int32 | fs_end_file_list (DEVICELIST *dev, void *handle) |
fs_end_file_list | |
static int32 | fs_rename_file (DEVICELIST *dev, uint8 *file1, uint8 *file2) |
The rename_file routine for the file system device type. | |
static int32 | fs_delete_file (DEVICELIST *dev, uint8 *filename) |
The delete_file routine for the file system device type. | |
static int32 | fs_set_param (DEVICELIST *dev, DEVICEPARAM *param) |
The set_param routine for the file system device type. More... | |
static int32 | fs_get_param (DEVICELIST *dev, DEVICEPARAM *param) |
The get_param routine for the file system device type. More... | |
static int32 | fs_status_device (DEVICELIST *dev, DEVSTAT *devstat) |
The status_device routine for the file system device type. More... | |
static int32 | fs_device_dismount (DEVICELIST *dev) |
The device_dismount routine for the file system device type. | |
static int32 | fs_ioctl (DEVICELIST *dev, DEVICE_FILEDESCRIPTOR descriptor, int32 opcode, intptr_t arg) |
The ioctl routine for the file system device type. | |
Variables | |
static int32 | fs_param_count = 0 |
The start_param routine for the file system device type. More... | |
DEVICETYPE | Fs_Device_Type |
The device type structure for the file system devices. More... | |
Implementation of the file system device type.
The device type interface is described in DEVICE interface.
This is a largely complete, though simple, implementation.
The most complex part is the implementation of the filenameforall operator through the three relevant functions in the device.
This is the device type which is assigned the device type number 0; see SDK devices and the DEVICE interface for a discussion of device type numbers.
A system which does not have a disk is still required to support a device type 0. However, the semantics would be different: it would only need to be readable, and supply known named files, such as SW/Sys/ExtraDevices
(which is essential) and built-in fonts. It could provide the byte stream for the read calls straight out of memory (ROM perhaps) rather than accessing a disk.
The operation of this implementation of the device type is that each device of this type represents a portion of the file system, e.g., on a PC the devices might be used to represent drives (%C%, %D%, ...) and on a Macintosh they represent volumes. There will always be a device %os% created implictly by the core rip, and this will usually be a restricted part of the file system: Harlequin's own products have a directory called "SW" by default which is what %os% refers to. Such a directory is supplied with the Core RIP library, including example system files, many of which may be used unchanged.
This implementation uses one device parameter, /Prefix
. This identifies where on the filing system the PostScript device is to refer to. This is a string representing a native pathname on the target file system. When PostScript refers to a file called "%p%aa/bb/cc", we map this to a name in the file system. This implementation does this by prefixing the name passed to the open call ("aa/bb/cc") with the prefix for the device (which is assumed to terminate with a '/'). The prefix is stored in the private data field of the devicelist structure for each device.
There is nothing special about the /
in the PostScript name, but we map it to the platform's directory separator. This has two consequences: because the semantics of the name "aa/bb/cc" are those of a flat file system, when a request is made to open the file for writing, if we are to use the same name, we must create any directories in the path in order to open the file. The mapping also means that we ignore the difference between files called "aa/bb/cc/" and "aa/bb/cc". These are both valid PostScript names and should refer to different files, but are mapped to the same file in this implementation. To be strictly correct this should be handled by some more sophisticated name mapping.
Some names will causes failures, e.g., names with an embedded colon on Windows. To overcome this some name mapping mechanism would need to be implemented.
The /Prefix
is obtained by the setdevparams
PostScript operator, so a useful piece of PostScript (to go in SW/Sys/ExtraDevices
, for example) would be:
statusdict begin (%%cd%) dup devmount pop << /Password 0 /DeviceType 0 /Prefix (./) /Enable true >> setdevparams end
(devmount
is not listed in the PostScript Language Reference Manual, but is found in all PostScript rips with file systems).
However, there is no PostScript associated with mounting the %os%
device: it needs to exist in order for SW/Sys/ExtraDevices
to be executed. This implementation assumes its prefix is always SW/
(i.e., a directory called SW in the current working directory). More general solutions include obtaining this from an environment variable, configuration file or command line option.
Though almost complete more general consideration might be given to the following:
|
static |
The bytes_file routine for the file system device type.
reason SW_BYTES_AVAIL_REL - immediately available after current pos reason SW_BYTES_TOTAL_ABS - total extent of file in bytes
|
static |
The close_file routine for the file system device type.
The abort call also invokes this function, because an abnormal close is the same as a normal close for the file system device type.
|
static |
File system device initialisation.
This is called for each device (note: not device type) when its type number is assigned by a call to setdevparams.
|
static |
The get_param routine for the file system device type.
This routine serves two purposes: when the parameter name is NULL, it is to return the next device parameter - fs_param_count keeps track of how far through the list we are, though in this case there is only one - otherwise it should return the one called for by the name.
|
static |
A device type function stub that raises an IOerror.
|
static |
The read_file routine for the file system device type.
Read from file described by 'descriptor' which is on the device 'dev' into the buffer 'buff'.
For abnormally large buffers (only when the device requests such sizes by the appropriate device type call), reading from the file system in chunks might be required, with SwOften calls between each.
|
static |
The set_param routine for the file system device type.
The only parameter that this implementation recognises is /Prefix, which must be a string, and it is used to define the prefix which is tacked on to the beginning of any filename requested by Harlequin RIP.
|
static |
Stub routine for spare device type slot.
|
static |
The status_device routine for the file system device type.
This is in contrast to status_file: it returns information about a device of this device type, rather than a file open on the device. The comprehensive implementation of this routine is likely to be complex. The example here simply gives no useful information.
|
static |
The write_file routine for the file system device type.
Write to the file described by 'descriptor' which is on the device 'dev' from the buffer 'buff'.
The comment for reading regarding SwOften also applies here.
|
static |
Initialise a FileDeviceState object.
pDeviceState should point to preallocated memory.
DEVICETYPE Fs_Device_Type |
The device type structure for the file system devices.
Points to note: (a) of the function pointers included in this structure, only the tickle function should be a NULL pointer. The rest must be filled in with stub routines which at least set the last error flag appropriately. (b) the device is "relative" (it can support named files, unlike, for example, a serial line). This means that when an attempt is made to open a named file in PostScript unqualified by a device, devices of this type will each receive open requests until one does not report an "undefined" error. See SDK DG 10.7.2. (c) the device is "writable": this means that devices of this type will be considered when trying to open a file for writing from PostScript.
|
static |
The start_param routine for the file system device type.
The routine is called as part of the currentdevparams operator; the individual parameters are returned one at a time by subsequent calls to the get_param function. fs_param_count is used to maintain the state between calls to get_param.
Also return the number of parameters recognized by this implementation of the file system device type.