diff options
Diffstat (limited to 'gs/base/gsiodev.c')
-rw-r--r-- | gs/base/gsiodev.c | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/gs/base/gsiodev.c b/gs/base/gsiodev.c new file mode 100644 index 000000000..d4ceec73d --- /dev/null +++ b/gs/base/gsiodev.c @@ -0,0 +1,353 @@ +/* Copyright (C) 2001-2006 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + + This software is distributed under license and may not be copied, modified + or distributed except as expressly authorized under the terms of that + license. Refer to licensing information at http://www.artifex.com/ + or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, + San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. +*/ + +/* $Id$ */ +/* IODevice implementation for Ghostscript */ +#include "errno_.h" +#include "string_.h" +#include "unistd_.h" +#include "gx.h" +#include "gserrors.h" +#include "gp.h" +#include "gscdefs.h" +#include "gsparam.h" +#include "gsstruct.h" +#include "gxiodev.h" + +/* Import the IODevice table from gconf.c. */ +extern_gx_io_device_table(); + +/* Define a table of local copies of the IODevices, */ +/* allocated at startup. This just postpones the day of reckoning.... */ +static gx_io_device **io_device_table; + +private_st_io_device(); +gs_private_st_ptr(st_io_device_ptr, gx_io_device *, "gx_io_device *", + iodev_ptr_enum_ptrs, iodev_ptr_reloc_ptrs); +gs_private_st_element(st_io_device_ptr_element, gx_io_device *, + "gx_io_device *[]", iodev_ptr_elt_enum_ptrs, iodev_ptr_elt_reloc_ptrs, + st_io_device_ptr); + +/* Define the OS (%os%) device. */ +iodev_proc_fopen(iodev_os_fopen); +iodev_proc_fclose(iodev_os_fclose); +static iodev_proc_delete_file(os_delete); +static iodev_proc_rename_file(os_rename); +static iodev_proc_file_status(os_status); +static iodev_proc_enumerate_files(os_enumerate); +static iodev_proc_get_params(os_get_params); +const gx_io_device gs_iodev_os = +{ + "%os%", "FileSystem", + {iodev_no_init, iodev_no_open_device, + NULL /*iodev_os_open_file */ , iodev_os_fopen, iodev_os_fclose, + os_delete, os_rename, os_status, + os_enumerate, gp_enumerate_files_next, gp_enumerate_files_close, + os_get_params, iodev_no_put_params + } +}; + +/* ------ Initialization ------ */ + +init_proc(gs_iodev_init); /* check prototype */ +int +gs_iodev_init(gs_memory_t * mem) +{ /* Make writable copies of all IODevices. */ + gx_io_device **table = + gs_alloc_struct_array(mem, gx_io_device_table_count, + gx_io_device *, &st_io_device_ptr_element, + "gs_iodev_init(table)"); + int i, j; + int code = 0; + + if (table == 0) + return_error(gs_error_VMerror); + for (i = 0; i < gx_io_device_table_count; ++i) { + gx_io_device *iodev = + gs_alloc_struct(mem, gx_io_device, &st_io_device, + "gs_iodev_init(iodev)"); + + if (iodev == 0) + goto fail; + table[i] = iodev; + memcpy(table[i], gx_io_device_table[i], sizeof(gx_io_device)); + } + io_device_table = table; + code = gs_register_struct_root(mem, NULL, (void **)&io_device_table, + "io_device_table"); + if (code < 0) + goto fail; + /* Run the one-time initialization of each IODevice. */ + for (j = 0; j < gx_io_device_table_count; ++j) + if ((code = (table[j]->procs.init)(table[j], mem)) < 0) + goto f2; + return 0; + f2: + /****** CAN'T FIND THE ROOT ******/ + /*gs_unregister_root(mem, root, "io_device_table");*/ + fail: + for (; i >= 0; --i) + gs_free_object(mem, table[i - 1], "gs_iodev_init(iodev)"); + gs_free_object(mem, table, "gs_iodev_init(table)"); + io_device_table = 0; + return (code < 0 ? code : gs_note_error(gs_error_VMerror)); +} + +/* ------ Default (unimplemented) IODevice procedures ------ */ + +int +iodev_no_init(gx_io_device * iodev, gs_memory_t * mem) +{ + return 0; +} + +int +iodev_no_open_device(gx_io_device * iodev, const char *access, stream ** ps, + gs_memory_t * mem) +{ + return_error(gs_error_invalidfileaccess); +} + +int +iodev_no_open_file(gx_io_device * iodev, const char *fname, uint namelen, + const char *access, stream ** ps, gs_memory_t * mem) +{ + return_error(gs_error_invalidfileaccess); +} + +int +iodev_no_fopen(gx_io_device * iodev, const char *fname, const char *access, + FILE ** pfile, char *rfname, uint rnamelen) +{ + return_error(gs_error_invalidfileaccess); +} + +int +iodev_no_fclose(gx_io_device * iodev, FILE * file) +{ + return_error(gs_error_ioerror); +} + +int +iodev_no_delete_file(gx_io_device * iodev, const char *fname) +{ + return_error(gs_error_invalidfileaccess); +} + +int +iodev_no_rename_file(gx_io_device * iodev, const char *from, const char *to) +{ + return_error(gs_error_invalidfileaccess); +} + +int +iodev_no_file_status(gx_io_device * iodev, const char *fname, struct stat *pstat) +{ + return_error(gs_error_undefinedfilename); +} + +file_enum * +iodev_no_enumerate_files(gx_io_device * iodev, const char *pat, uint patlen, + gs_memory_t * memory) +{ + return NULL; +} + +int +iodev_no_get_params(gx_io_device * iodev, gs_param_list * plist) +{ + return 0; +} + +int +iodev_no_put_params(gx_io_device * iodev, gs_param_list * plist) +{ + return param_commit(plist); +} + +/* ------ %os% ------ */ + +/* The fopen routine is exported for %null. */ +int +iodev_os_fopen(gx_io_device * iodev, const char *fname, const char *access, + FILE ** pfile, char *rfname, uint rnamelen) +{ + errno = 0; + *pfile = gp_fopen(fname, access); + if (*pfile == NULL) + return_error(gs_fopen_errno_to_code(errno)); + if (rfname != NULL && rfname != fname) + strcpy(rfname, fname); + return 0; +} + +/* The fclose routine is exported for %null. */ +int +iodev_os_fclose(gx_io_device * iodev, FILE * file) +{ + fclose(file); + return 0; +} + +static int +os_delete(gx_io_device * iodev, const char *fname) +{ + return (unlink(fname) == 0 ? 0 : gs_error_ioerror); +} + +static int +os_rename(gx_io_device * iodev, const char *from, const char *to) +{ + return (rename(from, to) == 0 ? 0 : gs_error_ioerror); +} + +static int +os_status(gx_io_device * iodev, const char *fname, struct stat *pstat) +{ /* The RS/6000 prototype for stat doesn't include const, */ + /* so we have to explicitly remove the const modifier. */ + return (stat((char *)fname, pstat) < 0 ? gs_error_undefinedfilename : 0); +} + +static file_enum * +os_enumerate(gx_io_device * iodev, const char *pat, uint patlen, + gs_memory_t * mem) +{ + return gp_enumerate_files_init(pat, patlen, mem); +} + +static int +os_get_params(gx_io_device * iodev, gs_param_list * plist) +{ + int code; + int i0 = 0, i2 = 2; + bool btrue = true, bfalse = false; + int BlockSize; + long Free, LogicalSize; + + /* + * Return fake values for BlockSize and Free, since we can't get the + * correct values in a platform-independent manner. + */ + BlockSize = 1024; + LogicalSize = 2000000000 / BlockSize; /* about 2 Gb */ + Free = LogicalSize * 3 / 4; /* about 1.5 Gb */ + + if ( + (code = param_write_bool(plist, "HasNames", &btrue)) < 0 || + (code = param_write_int(plist, "BlockSize", &BlockSize)) < 0 || + (code = param_write_long(plist, "Free", &Free)) < 0 || + (code = param_write_int(plist, "InitializeAction", &i0)) < 0 || + (code = param_write_bool(plist, "Mounted", &btrue)) < 0 || + (code = param_write_bool(plist, "Removable", &bfalse)) < 0 || + (code = param_write_bool(plist, "Searchable", &btrue)) < 0 || + (code = param_write_int(plist, "SearchOrder", &i2)) < 0 || + (code = param_write_bool(plist, "Writeable", &btrue)) < 0 || + (code = param_write_long(plist, "LogicalSize", &LogicalSize)) < 0 + ) + return code; + return 0; +} + +/* ------ Utilities ------ */ + +/* Get the N'th IODevice from the known device table. */ +gx_io_device * +gs_getiodevice(int index) +{ + if (!io_device_table || index < 0 || index >= gx_io_device_table_count) + return 0; /* index out of range */ + return io_device_table[index]; +} + +/* Look up an IODevice name. */ +/* The name may be either %device or %device%. */ +gx_io_device * +gs_findiodevice(const byte * str, uint len) +{ + int i; + + if (len > 1 && str[len - 1] == '%') + len--; + for (i = 0; i < gx_io_device_table_count; ++i) { + gx_io_device *iodev = io_device_table[i]; + const char *dname = iodev->dname; + + if (dname && strlen(dname) == len + 1 && !memcmp(str, dname, len)) + return iodev; + } + return 0; +} + +/* ------ Accessors ------ */ + +/* Get IODevice parameters. */ +int +gs_getdevparams(gx_io_device * iodev, gs_param_list * plist) +{ /* All IODevices have the Type parameter. */ + gs_param_string ts; + int code; + + param_string_from_string(ts, iodev->dtype); + code = param_write_name(plist, "Type", &ts); + if (code < 0) + return code; + return (*iodev->procs.get_params) (iodev, plist); +} + +/* Put IODevice parameters. */ +int +gs_putdevparams(gx_io_device * iodev, gs_param_list * plist) +{ + return (*iodev->procs.put_params) (iodev, plist); +} + +/* Convert an OS error number to a PostScript error */ +/* if opening a file fails. */ +int +gs_fopen_errno_to_code(int eno) +{ /* Different OSs vary widely in their error codes. */ + /* We try to cover as many variations as we know about. */ + switch (eno) { +#ifdef ENOENT + case ENOENT: + return_error(gs_error_undefinedfilename); +#endif +#ifdef ENOFILE +# ifndef ENOENT +# define ENOENT ENOFILE +# endif +# if ENOFILE != ENOENT + case ENOFILE: + return_error(gs_error_undefinedfilename); +# endif +#endif +#ifdef ENAMETOOLONG + case ENAMETOOLONG: + return_error(gs_error_undefinedfilename); +#endif +#ifdef EACCES + case EACCES: + return_error(gs_error_invalidfileaccess); +#endif +#ifdef EMFILE + case EMFILE: + return_error(gs_error_limitcheck); +#endif +#ifdef ENFILE + case ENFILE: + return_error(gs_error_limitcheck); +#endif + default: + return_error(gs_error_ioerror); + } +} |