1 /* Copyright (C) 2001-2019 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13    CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 /* %ram% file device implementation */
17 
18 /*
19  *  This file implements a simple ram-based file system.
20  *
21  * The fs has no subdirs, only a root directory. Files are stored as a
22  * resizable array of pointers to blocks.  Timestamps are not implemented
23  * for performance reasons.
24  *
25  * The implementation is in two parts - a ramfs interface that works
26  * mostly like the unix file system calls, and a layer to hook this up
27  * to ghostscript.
28  *
29  * Macros define an upper limit on the number of blocks a ram device
30  * can take up, and (in ramfs.c) the size of each block.
31  *
32  * Routines for the gs stream interface were graciously stolen from
33  * sfxstdio.c et al.
34  */
35 
36 #include "string_.h"
37 #include "unistd_.h"
38 #include "gx.h"
39 #include "gserrors.h"
40 #include "gp.h"
41 #include "gscdefs.h"
42 #include "gsparam.h"
43 #include "gsstruct.h"
44 #include "gxiodev.h"
45 #include "gsutil.h"
46 #include "stream.h"
47 #include "ramfs.h"
48 
49 /* Function prototypes */
50 static iodev_proc_init(iodev_ram_init);
51 static iodev_proc_finit(iodev_ram_finit);
52 static iodev_proc_open_file(ram_open_file);
53 static iodev_proc_delete_file(ram_delete);
54 static iodev_proc_rename_file(ram_rename);
55 static iodev_proc_file_status(ram_status);
56 static iodev_proc_enumerate_files(ram_enumerate_init);
57 static iodev_proc_enumerate_next(ram_enumerate_next);
58 static iodev_proc_enumerate_close(ram_enumerate_close);
59 static iodev_proc_get_params(ram_get_params);
60 static void ram_finalize(const gs_memory_t *memory, void * vptr);
61 
62 const gx_io_device gs_iodev_ram = {
63     "%ram%", "FileSystem", {
64         iodev_ram_init, iodev_ram_finit, iodev_no_open_device,
65         ram_open_file, iodev_no_fopen, iodev_no_fclose,
66         ram_delete, ram_rename, ram_status,
67         ram_enumerate_init, ram_enumerate_next, ram_enumerate_close,
68         ram_get_params, iodev_no_put_params
69     },
70     NULL,
71     NULL
72 };
73 
74 typedef struct ramfs_state_s {
75     gs_memory_t *memory;
76     ramfs* fs;
77 } ramfs_state;
78 
79 #define GETRAMFS(state) (((ramfs_state*)(state))->fs)
80 
81 gs_private_st_simple_final(st_ramfs_state, struct ramfs_state_s, "ramfs_state", ram_finalize);
82 
83 typedef struct gsram_enum_s {
84     char *pattern;
85     ramfs_enum* e;
86     gs_memory_t *memory;
87 } gsram_enum;
88 
89 gs_private_st_ptrs3(st_gsram_enum, struct gsram_enum_s, "gsram_enum",
90     gsram_enum_enum_ptrs, gsram_enum_reloc_ptrs, pattern, e, memory);
91 
92 /* could make this runtime configurable later.  It doesn't allocate
93    all the blocks in one go so it's not critical */
94 #define MAXBLOCKS 2000000
95 
96 #define DEFAULT_BUFFER_SIZE 2048
97 
98 /* stream stuff */
99 
100 static int
101 s_ram_available(stream *, gs_offset_t *),
102  s_ram_read_seek(stream *, gs_offset_t),
103  s_ram_read_close(stream *),
104  s_ram_read_process(stream_state *, stream_cursor_read *,
105      stream_cursor_write *, bool);
106 static int
107 s_ram_write_seek(stream *, gs_offset_t),
108  s_ram_write_flush(stream *),
109  s_ram_write_close(stream *),
110  s_ram_write_process(stream_state *, stream_cursor_read *,
111      stream_cursor_write *, bool);
112 static int
113 s_ram_switch(stream *, bool);
114 
115 static int
ramfs_errno_to_code(int error_number)116 ramfs_errno_to_code(int error_number) {
117     switch (error_number) {
118     case RAMFS_NOTFOUND:
119         return_error(gs_error_undefinedfilename);
120     case RAMFS_NOACCESS:
121         return_error(gs_error_invalidfileaccess);
122     case RAMFS_NOMEM:
123         return_error(gs_error_VMerror);
124     /* just in case */
125     default:
126         return_error(gs_error_ioerror);
127     }
128 }
129 
130 static void
131 sread_ram(register stream * s, ramhandle * file, byte * buf, uint len),
132  swrite_ram(register stream * s, ramhandle * file, byte * buf, uint len),
133  sappend_ram(register stream * s, ramhandle * file, byte * buf, uint len);
134 
135 static int
ram_open_file(gx_io_device * iodev,const char * fname,uint len,const char * file_access,stream ** ps,gs_memory_t * mem)136 ram_open_file(gx_io_device * iodev, const char *fname, uint len,
137     const char *file_access, stream ** ps, gs_memory_t * mem)
138 {
139     int code = 0;
140     ramhandle * file;
141     char fmode[4];  /* r/w/a, [+], [b], null */
142     int openmode=RAMFS_READ;
143     ramfs * fs;
144     char * namestr = NULL;
145 
146     /* Is there a more efficient way to do this? */
147     namestr = (char *)gs_alloc_bytes(mem, len + 1, "temporary filename string");
148     if(!namestr)
149         return_error(gs_error_VMerror);
150     strncpy(namestr,fname,len);
151     namestr[len] = 0;
152 
153     if (!iodev) {/*iodev = iodev_default;*/
154         gs_free_object(mem, namestr, "free temporary filename string");
155         return gs_note_error(gs_error_invalidaccess);
156     }
157     fs = GETRAMFS(iodev->state);
158     code = file_prepare_stream(fname, len, file_access, DEFAULT_BUFFER_SIZE,
159     ps, fmode, mem
160     );
161     if (code < 0) goto error;
162     if (fname == 0) {
163         gs_free_object(mem, namestr, "free temporary filename string");
164         return 0;
165     }
166 
167     switch (fmode[0]) {
168         case 'a':
169           openmode = RAMFS_WRITE | RAMFS_APPEND;
170           break;
171         case 'r':
172           openmode = RAMFS_READ;
173           if (fmode[1] == '+')
174             openmode |= RAMFS_WRITE;
175           break;
176         case 'w':
177           openmode |= RAMFS_WRITE | RAMFS_TRUNC | RAMFS_CREATE;
178           if (fmode[1] == '+')
179              openmode |= RAMFS_READ;
180     }
181 
182     /* For now, we cheat here in the same way that sfxstdio.c et al cheat -
183        append mode is faked by opening in write mode and seeking to EOF just
184        once. This is different from unix semantics, which seeks atomically
185        before each write, and is actually useful as a distinct mode. */
186     /* if (fmode[0] == 'a') openmode |= RAMFS_APPEND; */
187 
188     file = ramfs_open(mem, fs,namestr,openmode);
189     if(!file) { code = ramfs_errno_to_code(ramfs_error(fs)); goto error; }
190 
191     switch (fmode[0]) {
192     case 'a':
193     sappend_ram(*ps, file, (*ps)->cbuf, (*ps)->bsize);
194     break;
195     case 'r':
196     sread_ram(*ps, file, (*ps)->cbuf, (*ps)->bsize);
197     break;
198     case 'w':
199     swrite_ram(*ps, file, (*ps)->cbuf, (*ps)->bsize);
200     }
201     if (fmode[1] == '+') {
202       (*ps)->modes = (*ps)->file_modes |= s_mode_read | s_mode_write;
203     }
204     (*ps)->save_close = (*ps)->procs.close;
205     (*ps)->procs.close = file_close_file;
206  error:
207     gs_free_object(mem, namestr, "free temporary filename string");
208     /* XXX free stream stuff? */
209     return code;
210 }
211 
212 /* Initialize a stream for reading an OS file. */
213 static void
sread_ram(register stream * s,ramhandle * file,byte * buf,uint len)214 sread_ram(register stream * s, ramhandle * file, byte * buf, uint len)
215 {
216     static const stream_procs p = {
217     s_ram_available, s_ram_read_seek, s_std_read_reset,
218     s_std_read_flush, s_ram_read_close, s_ram_read_process,
219     s_ram_switch
220     };
221 
222     s_std_init(s, buf, len, &p,s_mode_read + s_mode_seek);
223     s->file = (gp_file *)file;
224     s->file_modes = s->modes;
225     s->file_offset = 0;
226     ramfile_seek(file, 0, RAMFS_SEEK_END);
227     s->file_limit = ramfile_tell(file);
228     ramfile_seek(file, 0, RAMFS_SEEK_SET);
229 }
230 
231 /* Procedures for reading from a file */
232 static int
s_ram_available(register stream * s,gs_offset_t * pl)233 s_ram_available(register stream * s, gs_offset_t *pl)
234 {
235     long max_avail = s->file_limit - stell(s);
236 
237     *pl = max_avail;
238     if(*pl == 0 && ramfile_eof((ramhandle*)s->file))
239     *pl = -1;        /* EOF */
240     return 0;
241 }
242 
243 static int
s_ram_read_seek(register stream * s,gs_offset_t pos)244 s_ram_read_seek(register stream * s, gs_offset_t pos)
245 {
246     uint end = s->cursor.r.limit - s->cbuf + 1;
247     long offset = pos - s->position;
248 
249     if (offset >= 0 && offset <= end) {  /* Staying within the same buffer */
250         s->cursor.r.ptr = s->cbuf + offset - 1;
251         return 0;
252     }
253     if (pos < 0 || pos > s->file_limit ||
254         ramfile_seek((ramhandle*)s->file, s->file_offset + pos, RAMFS_SEEK_SET) != 0
255     )
256     return ERRC;
257     s->cursor.r.ptr = s->cursor.r.limit = s->cbuf - 1;
258     s->end_status = 0;
259     s->position = pos;
260     return 0;
261 }
262 static int
s_ram_read_close(stream * s)263 s_ram_read_close(stream * s)
264 {
265     ramhandle *file = (ramhandle*)s->file;
266 
267     if (file != 0) {
268     s->file = 0;
269     ramfile_close(file);
270     }
271     return 0;
272 }
273 
274 /*
275  * Process a buffer for a file reading stream.
276  * This is the first stream in the pipeline, so pr is irrelevant.
277  */
278 static int
s_ram_read_process(stream_state * st,stream_cursor_read * ignore_pr,stream_cursor_write * pw,bool last)279 s_ram_read_process(stream_state * st, stream_cursor_read * ignore_pr,
280     stream_cursor_write * pw, bool last)
281 {
282     stream *s = (stream *)st;    /* no separate state */
283     ramhandle *file = (ramhandle*)s->file;
284     uint max_count = pw->limit - pw->ptr;
285     int status = 1;
286     int count;
287 
288     if (s->file_limit < S_FILE_LIMIT_MAX) {
289     long limit_count = s->file_offset + s->file_limit -
290     ramfile_tell(file);
291 
292     if (max_count > limit_count)
293         max_count = limit_count, status = EOFC;
294     }
295     count = ramfile_read(file,pw->ptr + 1, max_count);
296     if (count < 0) return ERRC;
297     pw->ptr += count;
298     /*    process_interrupts(s->memory); */
299     return ramfile_eof(file) ? EOFC : status;
300 }
301 
302 /* ------ File writing ------ */
303 
304 /* Initialize a stream for writing a file. */
305 static void
swrite_ram(register stream * s,ramhandle * file,byte * buf,uint len)306 swrite_ram(register stream * s, ramhandle * file, byte * buf, uint len)
307 {
308     static const stream_procs p = {
309     s_std_noavailable, s_ram_write_seek, s_std_write_reset,
310     s_ram_write_flush, s_ram_write_close, s_ram_write_process,
311     s_ram_switch
312     };
313 
314     s_std_init(s, buf, len, &p, s_mode_write + s_mode_seek);
315     s->file = (gp_file *)file;
316     s->file_modes = s->modes;
317     s->file_offset = 0;        /* in case we switch to reading later */
318     s->file_limit = S_FILE_LIMIT_MAX;
319 }
320 
321 /* Initialize for appending to a file. */
322 static void
sappend_ram(register stream * s,ramhandle * file,byte * buf,uint len)323 sappend_ram(register stream * s, ramhandle * file, byte * buf, uint len)
324 {
325     swrite_ram(s, file, buf, len);
326     s->modes = s_mode_write + s_mode_append;    /* no seek */
327     s->file_modes = s->modes;
328     ramfile_seek(file,0,RAMFS_SEEK_END);
329     s->position = ramfile_tell(file);
330 }
331 
332 /* Procedures for writing on a file */
333 static int
s_ram_write_seek(stream * s,gs_offset_t pos)334 s_ram_write_seek(stream * s, gs_offset_t pos)
335 {
336     /* We must flush the buffer to reposition. */
337     int code = sflush(s);
338 
339     if (code < 0) return code;
340     if (ramfile_seek((ramhandle*)s->file, pos, RAMFS_SEEK_SET) != 0)
341     return ERRC;
342     s->position = pos;
343     return 0;
344 }
345 
346 static int
s_ram_write_flush(register stream * s)347 s_ram_write_flush(register stream * s)
348 {
349     int result = s_process_write_buf(s, false);
350     return result;
351 }
352 
353 static int
s_ram_write_close(register stream * s)354 s_ram_write_close(register stream * s)
355 {
356     s_process_write_buf(s, true);
357     return s_ram_read_close(s);
358 }
359 
360 /*
361  * Process a buffer for a file writing stream.
362  * This is the last stream in the pipeline, so pw is irrelevant.
363  */
364 static int
s_ram_write_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * ignore_pw,bool last)365 s_ram_write_process(stream_state * st, stream_cursor_read * pr,
366     stream_cursor_write * ignore_pw, bool last)
367 {
368     uint count = pr->limit - pr->ptr;
369 
370     ramhandle *file = (ramhandle*)((stream *) st)->file;
371     int written = ramfile_write(file,pr->ptr + 1, count);
372 
373     if (written < 0) return ERRC;
374     pr->ptr += written;
375     return 0;
376 }
377 
378 static int
s_ram_switch(stream * s,bool writing)379 s_ram_switch(stream * s, bool writing)
380 {
381     uint modes = s->file_modes;
382     ramhandle *file = (ramhandle*)s->file;
383     long pos;
384 
385     if (writing) {
386     if (!(s->file_modes & s_mode_write)) return ERRC;
387     pos = stell(s);
388     ramfile_seek(file, pos, RAMFS_SEEK_SET);
389     if (modes & s_mode_append) {
390         sappend_ram(s, file, s->cbuf, s->cbsize);    /* sets position */
391     } else {
392         swrite_ram(s, file, s->cbuf, s->cbsize);
393         s->position = pos;
394     }
395     s->modes = modes;
396     } else {
397     if (!(s->file_modes & s_mode_read)) return ERRC;
398     pos = stell(s);
399     if (sflush(s) < 0) return ERRC;
400     sread_ram(s, file, s->cbuf, s->cbsize);
401     s->modes |= modes & s_mode_append;    /* don't lose append info */
402     s->position = pos;
403     }
404     s->file_modes = modes;
405     return 0;
406 }
407 
408 
409 /* gx_io_device stuff */
410 
411 static int
iodev_ram_init(gx_io_device * iodev,gs_memory_t * mem)412 iodev_ram_init(gx_io_device * iodev, gs_memory_t * mem)
413 {
414     ramfs* fs = ramfs_new(mem, MAXBLOCKS);
415     ramfs_state* state = gs_alloc_struct(mem, ramfs_state, &st_ramfs_state,
416     "ramfs_init(state)"
417     );
418     if (fs && state) {
419     state->fs = fs;
420     state->memory = mem;
421     iodev->state = state;
422     return 0;
423     }
424     if(fs) ramfs_destroy(mem, fs);
425     if(state) gs_free_object(mem,state,"iodev_ram_init(state)");
426     return_error(gs_error_VMerror);
427 }
428 
429 static void
iodev_ram_finit(gx_io_device * iodev,gs_memory_t * mem)430 iodev_ram_finit(gx_io_device * iodev, gs_memory_t * mem)
431 {
432     ramfs_state *state = (ramfs_state *)iodev->state;
433     if (state != NULL)
434     {
435         iodev->state = NULL;
436         gs_free_object(state->memory, state, "iodev_ram_finit");
437     }
438     return;
439 }
440 
441 static void
ram_finalize(const gs_memory_t * memory,void * vptr)442 ram_finalize(const gs_memory_t *memory, void * vptr)
443 {
444     ramfs* fs = GETRAMFS((ramfs_state*)vptr);
445     ramfs_destroy((gs_memory_t *)memory, fs);
446     GETRAMFS((ramfs_state*)vptr) = NULL;
447 }
448 
449 static int
ram_delete(gx_io_device * iodev,const char * fname)450 ram_delete(gx_io_device * iodev, const char *fname)
451 {
452     ramfs* fs = GETRAMFS(iodev->state);
453 
454     if(ramfs_unlink(fs,fname)!=0) {
455     return_error(ramfs_errno_to_code(ramfs_error(fs)));
456     }
457     return 0;
458 }
459 
460 static int
ram_rename(gx_io_device * iodev,const char * from,const char * to)461 ram_rename(gx_io_device * iodev, const char *from, const char *to)
462 {
463     ramfs* fs = GETRAMFS(iodev->state);
464 
465     if(ramfs_rename(fs,from,to)!=0) {
466     return_error(ramfs_errno_to_code(ramfs_error(fs)));
467     }
468     return 0;
469 }
470 
471 static int
ram_status(gx_io_device * iodev,const char * fname,struct stat * pstat)472 ram_status(gx_io_device * iodev, const char *fname, struct stat *pstat)
473 {
474     ramhandle * f;
475     ramfs* fs = GETRAMFS(iodev->state);
476 
477     f = ramfs_open(((ramfs_state *)iodev->state)->memory, fs,fname,RAMFS_READ);
478     if(!f) return_error(ramfs_errno_to_code(ramfs_error(fs)));
479 
480     memset(pstat, 0, sizeof(*pstat));
481     pstat->st_size = ramfile_size(f);
482     /* The Windows definition of struct stat doesn't include a st_blocks member
483     pstat->st_blocks = (pstat->st_size+blocksize-1)/blocksize;*/
484     /* XXX set mtime & ctime */
485     ramfile_close(f);
486     return 0;
487 }
488 
489 static file_enum *
ram_enumerate_init(gs_memory_t * mem,gx_io_device * iodev,const char * pat,uint patlen)490 ram_enumerate_init(gs_memory_t * mem, gx_io_device *iodev, const char *pat,
491                    uint patlen)
492 {
493     gsram_enum * penum = gs_alloc_struct(
494     mem, gsram_enum, &st_gsram_enum,
495     "ram_enumerate_files_init(file_enum)"
496     );
497     char *pattern = (char *)gs_alloc_bytes(
498     mem, patlen+1, "ram_enumerate_file_init(pattern)"
499     );
500 
501     ramfs_enum * e = ramfs_enum_new(GETRAMFS(iodev->state));
502     if(penum && pattern && e) {
503     memcpy(pattern, pat, patlen);
504     pattern[patlen]=0;
505 
506     penum->memory = mem;
507     penum->pattern = pattern;
508     penum->e = e;
509     return (file_enum *)penum;
510     }
511     if (penum) gs_free_object(mem,penum,"ramfs_enum_init(ramfs_enum)");
512     if (pattern)
513     gs_free_object(mem, pattern, "ramfs_enum_init(pattern)");
514     if(e) ramfs_enum_end(e);
515     return NULL;
516 }
517 
518 static void
ram_enumerate_close(gs_memory_t * mem,file_enum * pfen)519 ram_enumerate_close(gs_memory_t * mem, file_enum *pfen)
520 {
521     gsram_enum *penum = (gsram_enum *)pfen;
522     gs_memory_t *mem2 = penum->memory;
523     (void)mem;
524 
525     ramfs_enum_end(penum->e);
526     gs_free_object(mem2, penum->pattern, "ramfs_enum_init(pattern)");
527     gs_free_object(mem2, penum, "ramfs_enum_init(ramfs_enum)");
528 }
529 
530 static uint
ram_enumerate_next(gs_memory_t * mem,file_enum * pfen,char * ptr,uint maxlen)531 ram_enumerate_next(gs_memory_t * mem, file_enum *pfen, char *ptr, uint maxlen)
532 {
533     gsram_enum *penum = (gsram_enum *)pfen;
534 
535     char * filename;
536     while ((filename = ramfs_enum_next(penum->e))) {
537     if (string_match((byte *)filename, strlen(filename),
538         (byte *)penum->pattern,
539         strlen(penum->pattern), 0)) {
540         if (strlen(filename) < maxlen)
541         memcpy(ptr, filename, strlen(filename));
542         return strlen(filename);    /* if > maxlen, caller will detect rangecheck */
543     }
544     }
545     /* ran off end of list, close the enum */
546     ram_enumerate_close(mem, pfen);
547     return ~(uint)0;
548 }
549 
550 static int
ram_get_params(gx_io_device * iodev,gs_param_list * plist)551 ram_get_params(gx_io_device * iodev, gs_param_list * plist)
552 {
553     int code;
554     int i0 = 0, so = 1;
555     bool btrue = true, bfalse = false;
556     ramfs* fs = GETRAMFS(iodev->state);
557     int BlockSize;
558     long Free, LogicalSize;
559 
560     BlockSize = ramfs_blocksize(fs);
561     LogicalSize = MAXBLOCKS;
562     Free = ramfs_blocksfree(fs);
563 
564     if (
565     (code = param_write_bool(plist, "HasNames",        &btrue)) < 0 ||
566     (code = param_write_int (plist, "BlockSize",       &BlockSize)) < 0 ||
567     (code = param_write_long(plist, "Free",            &Free)) < 0 ||
568     (code = param_write_int (plist, "InitializeAction",&i0)) < 0 ||
569     (code = param_write_bool(plist, "Mounted",         &btrue)) < 0 ||
570     (code = param_write_bool(plist, "Removable",       &bfalse)) < 0 ||
571     (code = param_write_bool(plist, "Searchable",      &btrue)) < 0 ||
572     (code = param_write_int (plist, "SearchOrder",     &so)) < 0 ||
573     (code = param_write_bool(plist, "Writeable",       &btrue)) < 0 ||
574     (code = param_write_long(plist, "LogicalSize",     &LogicalSize)) < 0
575     )
576     return code;
577     return 0;
578 }
579