Bug 226943

Summary: There's no %ram% device.
Product: Ghostscript Reporter: Jack Moffitt <jack>
Component: PS InterpreterAssignee: Ray Johnston <ray.johnston>
Severity: enhancement Keywords: bountiable
Priority: P4    
Version: master   
Hardware: All   
OS: All   
Customer: Word Size: ---
Attachments: preliminary patches for %ram*% device family
%ram% device

Description Jack Moffitt 2000-12-27 20:35:28 UTC
Originally reported by: nobody@users.sourceforge.net
GS doesn't have %ram% device reguired on all Level 3 products.
it is documented in PS Supplement 3010 and 3011 dated August 30, 1999

Comment 1 L. Peter Deutsch 2000-12-31 09:45:30 UTC
Comment originally by lpd@users.sourceforge.net
Yes, this should be implemented. As Alex suggested, it can be implemented using the (disk) file system rather than actual RAM, and I think it should be implemented this way, at least initially, since that will be easy. On Unix, I suggest it be implemented with a directory /tmp/$$/ (where $$ is the process id), which Ghostscript should delete when it exits.
Comment 2 Ray Johnston 2001-04-03 18:17:18 UTC
Comment originally by rayjj@users.sourceforge.net
Logged In: YES 

You've pointed out a useful enhancement to Ghostscript. We don't
have plans to implement it at the moment, but we are adding it to
the Project.htm file within the Ghostscript distribution. With
luck, someone will pick the project up for implementation at some
later date.

Thanks for your input!
Comment 3 Stefan Kemper 2005-07-06 13:29:03 UTC
Customer request for feature
Comment 4 Ray Johnston 2005-07-08 09:06:43 UTC
This is a fairly straightforward feature to implement.

Ghostscript has provisions for adding "IODevice" entries such as the 'diskn'
(e.g. %disk0%, %disk1%, ...) that implements a flat file naming system independent
of the underlying %os% file system. Much of the diskn device can be used as an
example since this IODevice implements (in gsiodisk.c):
     iodev_diskn_init, iodev_diskn_fopen, diskn_delete, diskn_rename,
     diskn_status, diskn_enumerate_files_init, diskn_enumerate_next,
     diskn_enumerate_close, diskn_get_params, diskn_put_params 

A %ram% device will also need a _fclose function and probably can do without
any 'put_params' or 'get_params' special handling since initialization can be
done in the _init call.

The initial implementation would probably maintain a linked list of "files"
maintained in enumeration order. The file contents initially could just be
single allocations or could be a more sophisticated chain of compressed
blocks. I don't see any reason these allocations need to be garbage collected
thus avoiding the need for 'st_' GC structure definitions.
Comment 5 Michael (Micksa) Slade 2006-06-18 07:25:02 UTC
So which is bountiable?  Real RAM disk or pretend RAM mapped to temp dir?
Comment 6 Ray Johnston 2006-09-13 09:02:48 UTC
No response on using the %disk device for font downloading from customer.
Removing customer ID, but leaving bountiable bug open at P4 priority.
Comment 7 david d zuhn 2006-09-30 19:31:14 UTC
Created attachment 2517 [details]
preliminary patches for %ram*% device family

Here's a set of patches which implement most of the things needed for a %ram%
device.  It uses the temporary directory and real files approach.   It's not
yet complete (the directory and files are not automatically removed at program
exit).	 Other concerns are noted in the patch file itself.   

This patch is against v8.54.
Comment 8 Michael (Micksa) Slade 2007-01-18 21:43:05 UTC
Created attachment 2700 [details]
%ram% device

I risk shaking things up a little doing this but I'll give it a shot.

Attached is a patch for a *real* RAM device.

It comes in 2 parts - ramfs.[ch] which provides the ram device itself with a
unix-like interface, and gsioram.c which turns it into %ram%.

The device does not support subdirectories.  The single directory is stored as
a linked list.	Each file's data is stored as a dynmically extended array of
blocks, known as a hashed array tree in some circles.  It uses inodes so you
can safely delete open files, etc.

I have given it a basic but pretty thorough test, but haven't written a full
hardcore test suite for it since I'm sure someone at ghostscript.com has
something that can test it to death.

The makefile voodoo I've added is probably not the Right Way to compile it in
so could someone please check up on this, thanks.

Also please try it out and let me know if it works or doesn't work for you.
Comment 9 Ken Sharp 2013-06-21 16:09:03 UTC
I'm trying to contact Michael Slade with regards to this bug, if anyone has current contact details, can they please let me know.
Comment 10 Ken Sharp 2013-09-11 05:23:56 UTC
commits b5472ea6bf6925023febdeab12be9dbd83e811f1 
and db45b95faa06f8204b9a075323125d7f398c5d06 implement the patches from Michael Slade with some modifications to replace the system memory handling with Ghostscript garbage collected memory handling.
Comment 11 Ray Johnston 2017-01-21 15:07:57 UTC
This still has confusion with the memory handling. It had numerous problems
that I have fixed that primarily would keep it from doing anything with a
file more than 1024 characters, but when gs exits it segfaults even with my

Also changed the "this" local name to "thisdirent" so that the VS debugger
doesn't think it is a C++ thingy.

I'll push a partial fix to my repo in case anyone wants to review the changes.
Comment 13 Ray Johnston 2017-01-21 15:23:14 UTC
Created attachment 13304 [details]

A sample test file that can be used for testing. So far it is able to copy
the file correctly to "x" on the cwd, but fails in trying to use the file to
process it with 'runpdf', error report:

   **** Error: Cannot find a 'startxref' anywhere in the file.
               Output may be incorrect.
   **** Error:  An error occurred while reading an XREF table.
   **** The file has been damaged.  This may have been caused
   **** by a problem while converting or transfering the file.
   **** Ghostscript will attempt to recover the data.
   **** However, the output may be incorrect.
Error: /rangecheck in --string--

then gets a segfault during exiting.
Comment 14 Ray Johnston 2017-01-23 10:38:37 UTC
Created attachment 13308 [details]

This example copies stdin to a ram file, then runs it.

Commented out code also copies the file to disk so it can be checked
against the inputfile that is sent to stdin
Comment 15 Ray Johnston 2017-01-23 11:03:25 UTC
Fixed in commit eead75f44a03517ad50702f3c65d8c5784b4bfbb

There were problems with the GC not tracing the s->file pointer from the
stream (assumed to be an OS item) so change to using non_gc_memory. Also
problems with writing buffers more that a single block (not advancing
in the source buffer).

The bytesavailable operator didn't work because there was a bogus file_limit
in the stream, and s_ram_available was wrong.

Change the "this" to "thisdirent" so that C++ debuggers (like VS) can
show the structure contents correctly.

The ramfstest.ps is an example that can be used to run a PDF file from
stdin without needing to write a file to disk.