Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gsioram.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 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.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, 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_fopen(ram_fopen);
54
static iodev_proc_fclose(ram_fclose);
55
static iodev_proc_delete_file(ram_delete);
56
static iodev_proc_rename_file(ram_rename);
57
static iodev_proc_file_status(ram_status);
58
static iodev_proc_enumerate_files(ram_enumerate_init);
59
static iodev_proc_enumerate_next(ram_enumerate_next);
60
static iodev_proc_enumerate_close(ram_enumerate_close);
61
static iodev_proc_get_params(ram_get_params);
62
static void ram_finalize(const gs_memory_t *memory, void * vptr);
63
64
const gx_io_device gs_iodev_ram = {
65
    "%ram%", "FileSystem", {
66
        iodev_ram_init, iodev_ram_finit, iodev_no_open_device,
67
        ram_open_file, ram_fopen, ram_fclose,
68
        ram_delete, ram_rename, ram_status,
69
        ram_enumerate_init, ram_enumerate_next, ram_enumerate_close,
70
        ram_get_params, iodev_no_put_params
71
    },
72
    NULL,
73
    NULL
74
};
75
76
typedef struct ramfs_state_s {
77
    gs_memory_t *memory;
78
    ramfs* fs;
79
} ramfs_state;
80
81
381k
#define GETRAMFS(state) (((ramfs_state*)(state))->fs)
82
83
gs_private_st_simple_final(st_ramfs_state, struct ramfs_state_s, "ramfs_state", ram_finalize);
84
85
typedef struct gsram_enum_s {
86
    char *pattern;
87
    ramfs_enum* e;
88
    gs_memory_t *memory;
89
} gsram_enum;
90
91
gs_private_st_ptrs2(st_gsram_enum, struct gsram_enum_s, "gsram_enum",
92
    gsram_enum_enum_ptrs, gsram_enum_reloc_ptrs, pattern, memory);
93
94
/* could make this runtime configurable later.  It doesn't allocate
95
   all the blocks in one go so it's not critical */
96
190k
#define MAXBLOCKS 2000000
97
98
0
#define DEFAULT_BUFFER_SIZE 2048
99
100
/* stream stuff */
101
102
static int
103
s_ram_available(stream *, gs_offset_t *),
104
 s_ram_read_seek(stream *, gs_offset_t),
105
 s_ram_read_close(stream *),
106
 s_ram_read_process(stream_state *, stream_cursor_read *,
107
     stream_cursor_write *, bool);
108
static int
109
s_ram_write_seek(stream *, gs_offset_t),
110
 s_ram_write_flush(stream *),
111
 s_ram_write_close(stream *),
112
 s_ram_write_process(stream_state *, stream_cursor_read *,
113
     stream_cursor_write *, bool);
114
static int
115
s_ram_switch(stream *, bool);
116
117
static int
118
0
ramfs_errno_to_code(int error_number) {
119
0
    switch (error_number) {
120
0
    case RAMFS_NOTFOUND:
121
0
        return_error(gs_error_undefinedfilename);
122
0
    case RAMFS_NOACCESS:
123
0
        return_error(gs_error_invalidfileaccess);
124
0
    case RAMFS_NOMEM:
125
0
        return_error(gs_error_VMerror);
126
0
    case RAMFS_BADRANGE:
127
0
        return_error(gs_error_rangecheck);
128
0
    case RAMFS_DELETEOPENFILE:
129
0
        return_error(gs_error_ioerror);
130
    /* just in case */
131
0
    default:
132
0
        return_error(gs_error_ioerror);
133
0
    }
134
0
}
135
136
static void
137
sread_ram(register stream * s, ramhandle * file, byte * buf, uint len),
138
 swrite_ram(register stream * s, ramhandle * file, byte * buf, uint len),
139
 sappend_ram(register stream * s, ramhandle * file, byte * buf, uint len);
140
141
static int
142
ram_open_file(gx_io_device * iodev, const char *fname, uint len,
143
    const char *file_access, stream ** ps, gs_memory_t * mem)
144
0
{
145
0
    int code = 0;
146
0
    ramhandle * file;
147
0
    char fmode[4];  /* r/w/a, [+], [b], null */
148
0
    int openmode=RAMFS_READ;
149
0
    ramfs * fs;
150
0
    char * namestr = NULL;
151
152
    /* Is there a more efficient way to do this? */
153
0
    namestr = (char *)gs_alloc_bytes(mem, len + 1, "temporary filename string");
154
0
    if(!namestr)
155
0
        return_error(gs_error_VMerror);
156
0
    strncpy(namestr,fname,len);
157
0
    namestr[len] = 0;
158
159
    /* Make sure iodev is valid, and we have initialised the RAM file system (state != NULL) */
160
0
    if (iodev == NULL || iodev->state == NULL) {/*iodev = iodev_default;*/
161
0
        gs_free_object(mem, namestr, "free temporary filename string");
162
0
        return gs_note_error(gs_error_invalidaccess);
163
0
    }
164
0
    fs = GETRAMFS(iodev->state);
165
0
    code = file_prepare_stream(fname, len, file_access, DEFAULT_BUFFER_SIZE,
166
0
    ps, fmode, mem
167
0
    );
168
0
    if (code < 0) goto error;
169
0
    if (fname == 0) {
170
0
        gs_free_object(mem, namestr, "free temporary filename string");
171
0
        return 0;
172
0
    }
173
174
0
    switch (fmode[0]) {
175
0
        case 'a':
176
0
          openmode = RAMFS_WRITE | RAMFS_APPEND;
177
0
          break;
178
0
        case 'r':
179
0
          openmode = RAMFS_READ;
180
0
          if (fmode[1] == '+')
181
0
            openmode |= RAMFS_WRITE;
182
0
          break;
183
0
        case 'w':
184
0
          openmode |= RAMFS_WRITE | RAMFS_TRUNC | RAMFS_CREATE;
185
0
          if (fmode[1] == '+')
186
0
             openmode |= RAMFS_READ;
187
0
    }
188
189
    /* For now, we cheat here in the same way that sfxstdio.c et al cheat -
190
       append mode is faked by opening in write mode and seeking to EOF just
191
       once. This is different from unix semantics, which seeks atomically
192
       before each write, and is actually useful as a distinct mode. */
193
    /* if (fmode[0] == 'a') openmode |= RAMFS_APPEND; */
194
195
0
    file = ramfs_open(mem, fs,namestr,openmode);
196
0
    if(!file) { code = ramfs_errno_to_code(ramfs_error(fs)); goto error; }
197
198
0
    switch (fmode[0]) {
199
0
    case 'a':
200
0
    sappend_ram(*ps, file, (*ps)->cbuf, (*ps)->bsize);
201
0
    break;
202
0
    case 'r':
203
0
    sread_ram(*ps, file, (*ps)->cbuf, (*ps)->bsize);
204
0
    break;
205
0
    case 'w':
206
0
    swrite_ram(*ps, file, (*ps)->cbuf, (*ps)->bsize);
207
0
    }
208
0
    if (fmode[1] == '+') {
209
0
      (*ps)->modes = (*ps)->file_modes |= s_mode_read | s_mode_write;
210
0
    }
211
0
    (*ps)->save_close = (*ps)->procs.close;
212
0
    (*ps)->procs.close = file_close_file;
213
0
 error:
214
0
    gs_free_object(mem, namestr, "free temporary filename string");
215
    /* XXX free stream stuff? */
216
0
    return code;
217
0
}
218
219
static const gp_file_ops_t gp_file_RAM_prototype =
220
{
221
    gp_file_ram_close,
222
    gp_file_ram_getc,
223
    gp_file_ram_putc,
224
    gp_file_ram_read,
225
    gp_file_ram_write,
226
    gp_file_ram_seek,
227
    gp_file_ram_tell,
228
    gp_file_ram_eof,
229
    gp_file_ram_dup,
230
    gp_file_ram_seekable,
231
    gp_file_ram_pread,
232
    gp_file_ram_pwrite,
233
    gp_file_ram_is_char_buffered,
234
    gp_file_ram_fflush,
235
    gp_file_ram_ferror,
236
    gp_file_ram_get_file,
237
    gp_file_ram_clearerror,
238
    gp_file_ram_reopen
239
};
240
241
static gp_file_RAM *gp_file_RAM_alloc(const gs_memory_t *mem)
242
0
{
243
0
    return (gp_file_RAM *)gp_file_alloc(mem->non_gc_memory,
244
0
                         &gp_file_RAM_prototype,
245
0
                         sizeof(gp_file_RAM),
246
0
                         "gp_file_RAM");
247
0
}
248
249
int ram_fopen(gx_io_device *iodev, const char *fname, const char *access,
250
              gp_file **pfile, char *rfname, uint rnamelen, gs_memory_t *mem)
251
0
{
252
0
    ramfs_state* state = (ramfs_state *)iodev->state;
253
0
    gp_file_RAM **file = (gp_file_RAM **)pfile;
254
0
    int i, mode = 0;
255
256
0
    *file = gp_file_RAM_alloc(mem);
257
0
    if (*file == NULL)
258
0
        return 0;
259
260
0
    for (i=0;i<strlen(access);i++) {
261
0
        if (access[i] == 'r')
262
0
            mode |= RAMFS_READ;
263
0
        else {
264
0
            if (access[i] == 'w') {
265
0
                mode |= RAMFS_WRITE;
266
0
                mode |= RAMFS_CREATE;
267
0
                mode |= RAMFS_TRUNC;
268
0
            }
269
0
            else
270
0
            {
271
0
                if (access[i] == 'a') {
272
0
                    mode |= RAMFS_APPEND;
273
0
                    mode |= RAMFS_CREATE;
274
0
                }
275
0
                else {
276
0
                    if (access[i] == '+') {
277
0
                        if (mode & RAMFS_WRITE)
278
0
                            mode |= RAMFS_READ;
279
0
                        else
280
0
                            mode |= RAMFS_WRITE;
281
0
                    }
282
0
                    else
283
0
                        if (access[i] == 'b')
284
0
                            ;
285
0
                        else
286
0
                            return 0;
287
0
                }
288
0
            }
289
0
        }
290
0
    }
291
0
    (*file)->handle = ramfs_open(iodev->memory, state->fs, fname, mode);
292
0
    if ((*file)->handle == NULL)
293
0
        return_error(gs_error_undefinedfilename);
294
295
0
    if (rfname != NULL && rfname != fname)
296
0
        strcpy(rfname, fname);
297
298
0
    return 0;
299
0
}
300
301
int ram_fclose(gx_io_device *iodev, gp_file *file)
302
0
{
303
0
    gp_file_RAM *pfile = (gp_file_RAM *)file;
304
305
0
    ramfile_close(pfile->handle);
306
0
    return 0;
307
0
}
308
309
/* Initialize a stream for reading an OS file. */
310
static void
311
sread_ram(register stream * s, ramhandle * file, byte * buf, uint len)
312
0
{
313
0
    static const stream_procs p = {
314
0
    s_ram_available, s_ram_read_seek, s_std_read_reset,
315
0
    s_std_read_flush, s_ram_read_close, s_ram_read_process,
316
0
    s_ram_switch
317
0
    };
318
319
0
    s_std_init(s, buf, len, &p,s_mode_read + s_mode_seek);
320
0
    s->file = (gp_file *)file;
321
0
    s->file_modes = s->modes;
322
0
    s->file_offset = 0;
323
0
    ramfile_seek(file, 0, RAMFS_SEEK_END);
324
0
    s->file_limit = ramfile_tell(file);
325
0
    ramfile_seek(file, 0, RAMFS_SEEK_SET);
326
0
}
327
328
/* Procedures for reading from a file */
329
static int
330
s_ram_available(register stream * s, gs_offset_t *pl)
331
0
{
332
0
    long max_avail = s->file_limit - stell(s);
333
334
0
    *pl = max_avail;
335
0
    if(*pl == 0 && ramfile_eof((ramhandle*)s->file))
336
0
    *pl = -1;        /* EOF */
337
0
    return 0;
338
0
}
339
340
static int
341
s_ram_read_seek(register stream * s, gs_offset_t pos)
342
0
{
343
0
    uint end = s->cursor.r.limit - s->cbuf + 1;
344
0
    long offset = pos - s->position;
345
346
0
    if (offset >= 0 && offset <= end) {  /* Staying within the same buffer */
347
0
        s->cursor.r.ptr = s->cbuf + offset - 1;
348
0
        return 0;
349
0
    }
350
351
0
    if (pos < 0 || pos > s->file_limit || s->file == NULL ||
352
0
        ramfile_seek((ramhandle*)s->file, s->file_offset + pos, RAMFS_SEEK_SET) != 0)
353
0
        return ERRC;
354
355
0
    s->cursor.r.ptr = s->cursor.r.limit = s->cbuf - 1;
356
0
    s->end_status = 0;
357
0
    s->position = pos;
358
0
    return 0;
359
0
}
360
static int
361
s_ram_read_close(stream * s)
362
0
{
363
0
    ramhandle *file = (ramhandle*)s->file;
364
365
0
    if (file != 0) {
366
0
    s->file = 0;
367
0
    ramfile_close(file);
368
0
    }
369
0
    return 0;
370
0
}
371
372
/*
373
 * Process a buffer for a file reading stream.
374
 * This is the first stream in the pipeline, so pr is irrelevant.
375
 */
376
static int
377
s_ram_read_process(stream_state * st, stream_cursor_read * ignore_pr,
378
    stream_cursor_write * pw, bool last)
379
0
{
380
0
    stream *s = (stream *)st;    /* no separate state */
381
0
    ramhandle *file = (ramhandle*)s->file;
382
0
    uint max_count = pw->limit - pw->ptr;
383
0
    int status = 1;
384
0
    int count;
385
386
0
    if (s->file_limit < S_FILE_LIMIT_MAX) {
387
0
    long limit_count = s->file_offset + s->file_limit -
388
0
    ramfile_tell(file);
389
390
0
    if (max_count > limit_count)
391
0
        max_count = limit_count, status = EOFC;
392
0
    }
393
0
    count = ramfile_read(file,pw->ptr + 1, max_count);
394
0
    if (count < 0) return ERRC;
395
0
    pw->ptr += count;
396
    /*    process_interrupts(s->memory); */
397
0
    return ramfile_eof(file) ? EOFC : status;
398
0
}
399
400
/* ------ File writing ------ */
401
402
/* Initialize a stream for writing a file. */
403
static void
404
swrite_ram(register stream * s, ramhandle * file, byte * buf, uint len)
405
0
{
406
0
    static const stream_procs p = {
407
0
    s_std_noavailable, s_ram_write_seek, s_std_write_reset,
408
0
    s_ram_write_flush, s_ram_write_close, s_ram_write_process,
409
0
    s_ram_switch
410
0
    };
411
412
0
    s_std_init(s, buf, len, &p, s_mode_write + s_mode_seek);
413
0
    s->file = (gp_file *)file;
414
0
    s->file_modes = s->modes;
415
0
    s->file_offset = 0;        /* in case we switch to reading later */
416
0
    s->file_limit = S_FILE_LIMIT_MAX;
417
0
}
418
419
/* Initialize for appending to a file. */
420
static void
421
sappend_ram(register stream * s, ramhandle * file, byte * buf, uint len)
422
0
{
423
0
    swrite_ram(s, file, buf, len);
424
0
    s->modes = s_mode_write + s_mode_append;    /* no seek */
425
0
    s->file_modes = s->modes;
426
0
    ramfile_seek(file,0,RAMFS_SEEK_END);
427
0
    s->position = ramfile_tell(file);
428
0
}
429
430
/* Procedures for writing on a file */
431
static int
432
s_ram_write_seek(stream * s, gs_offset_t pos)
433
0
{
434
    /* We must flush the buffer to reposition. */
435
0
    int code = sflush(s);
436
437
0
    if (code < 0) return code;
438
0
    if (pos < 0 || ramfile_seek((ramhandle*)s->file, pos, RAMFS_SEEK_SET) != 0)
439
0
        return ERRC;
440
0
    s->position = pos;
441
0
    return 0;
442
0
}
443
444
static int
445
s_ram_write_flush(register stream * s)
446
0
{
447
0
    int result = s_process_write_buf(s, false);
448
0
    return result;
449
0
}
450
451
static int
452
s_ram_write_close(register stream * s)
453
0
{
454
0
    s_process_write_buf(s, true);
455
0
    return s_ram_read_close(s);
456
0
}
457
458
/*
459
 * Process a buffer for a file writing stream.
460
 * This is the last stream in the pipeline, so pw is irrelevant.
461
 */
462
static int
463
s_ram_write_process(stream_state * st, stream_cursor_read * pr,
464
    stream_cursor_write * ignore_pw, bool last)
465
0
{
466
0
    uint count = pr->limit - pr->ptr;
467
468
0
    ramhandle *file = (ramhandle*)((stream *) st)->file;
469
0
    int written = ramfile_write(file,pr->ptr + 1, count);
470
471
0
    if (written < 0) return ERRC;
472
0
    pr->ptr += written;
473
0
    return 0;
474
0
}
475
476
static int
477
s_ram_switch(stream * s, bool writing)
478
0
{
479
0
    uint modes = s->file_modes;
480
0
    ramhandle *file = (ramhandle*)s->file;
481
0
    long pos;
482
483
0
    if (writing) {
484
0
    if (!(s->file_modes & s_mode_write)) return ERRC;
485
0
    pos = stell(s);
486
0
    ramfile_seek(file, pos, RAMFS_SEEK_SET);
487
0
    if (modes & s_mode_append) {
488
0
        sappend_ram(s, file, s->cbuf, s->cbsize);    /* sets position */
489
0
    } else {
490
0
        swrite_ram(s, file, s->cbuf, s->cbsize);
491
0
        s->position = pos;
492
0
    }
493
0
    s->modes = modes;
494
0
    } else {
495
0
    if (!(s->file_modes & s_mode_read)) return ERRC;
496
0
    pos = stell(s);
497
0
    if (sflush(s) < 0) return ERRC;
498
0
    sread_ram(s, file, s->cbuf, s->cbsize);
499
0
    s->modes |= modes & s_mode_append;    /* don't lose append info */
500
0
    s->position = pos;
501
0
    }
502
0
    s->file_modes = modes;
503
0
    return 0;
504
0
}
505
506
507
/* gx_io_device stuff */
508
509
static int
510
iodev_ram_init(gx_io_device * iodev, gs_memory_t * mem)
511
190k
{
512
190k
    ramfs* fs = ramfs_new(mem, MAXBLOCKS);
513
190k
    ramfs_state* state = gs_alloc_struct(mem, ramfs_state, &st_ramfs_state,
514
190k
    "ramfs_init(state)"
515
190k
    );
516
190k
    if (fs && state) {
517
190k
    state->fs = fs;
518
190k
    state->memory = mem;
519
190k
    iodev->state = state;
520
190k
    return 0;
521
190k
    }
522
0
    if(fs) ramfs_destroy(mem, fs);
523
0
    if(state) gs_free_object(mem,state,"iodev_ram_init(state)");
524
0
    return_error(gs_error_VMerror);
525
190k
}
526
527
static void
528
iodev_ram_finit(gx_io_device * iodev, gs_memory_t * mem)
529
61.1k
{
530
61.1k
    ramfs_state *state = (ramfs_state *)iodev->state;
531
61.1k
    if (state != NULL)
532
61.1k
    {
533
61.1k
        iodev->state = NULL;
534
61.1k
        gs_free_object(state->memory, state, "iodev_ram_finit");
535
61.1k
    }
536
61.1k
    return;
537
61.1k
}
538
539
static void
540
ram_finalize(const gs_memory_t *memory, void * vptr)
541
190k
{
542
190k
    ramfs* fs = GETRAMFS((ramfs_state*)vptr);
543
190k
    ramfs_destroy((gs_memory_t *)memory, fs);
544
190k
    GETRAMFS((ramfs_state*)vptr) = NULL;
545
190k
}
546
547
static int
548
ram_delete(gx_io_device * iodev, const char *fname)
549
0
{
550
0
    ramfs* fs;
551
552
0
    if (iodev->state == NULL)
553
0
        return_error(gs_error_ioerror);
554
0
    else
555
0
        fs = GETRAMFS(iodev->state);
556
557
0
    if(ramfs_unlink(fs,fname)!=0) {
558
0
    return_error(ramfs_errno_to_code(ramfs_error(fs)));
559
0
    }
560
0
    return 0;
561
0
}
562
563
static int
564
ram_rename(gx_io_device * iodev, const char *from, const char *to)
565
0
{
566
0
    ramfs* fs;
567
568
0
    if (iodev->state == NULL)
569
0
        return_error(gs_error_ioerror);
570
0
    else
571
0
        fs = GETRAMFS(iodev->state);
572
573
0
    if(ramfs_rename(fs,from,to)!=0) {
574
0
    return_error(ramfs_errno_to_code(ramfs_error(fs)));
575
0
    }
576
0
    return 0;
577
0
}
578
579
static int
580
ram_status(gx_io_device * iodev, const char *fname, struct stat *pstat)
581
0
{
582
0
    ramhandle * f;
583
0
    ramfs* fs;
584
585
0
    if (iodev->state == NULL)
586
0
        return_error(gs_error_ioerror);
587
0
    else
588
0
        fs = GETRAMFS(iodev->state);
589
590
0
    f = ramfs_open(((ramfs_state *)iodev->state)->memory, fs,fname,RAMFS_READ);
591
0
    if(!f) return_error(ramfs_errno_to_code(ramfs_error(fs)));
592
593
0
    memset(pstat, 0, sizeof(*pstat));
594
0
    pstat->st_size = ramfile_size(f);
595
    /* The Windows definition of struct stat doesn't include a st_blocks member
596
    pstat->st_blocks = (pstat->st_size+blocksize-1)/blocksize;*/
597
    /* XXX set mtime & ctime */
598
0
    ramfile_close(f);
599
0
    return 0;
600
0
}
601
602
static file_enum *
603
ram_enumerate_init(gs_memory_t * mem, gx_io_device *iodev, const char *pat,
604
                   uint patlen)
605
0
{
606
0
    gsram_enum * penum = gs_alloc_struct(
607
0
    mem, gsram_enum, &st_gsram_enum,
608
0
    "ram_enumerate_files_init(file_enum)"
609
0
    );
610
0
    char *pattern = (char *)gs_alloc_bytes(
611
0
    mem, patlen+1, "ram_enumerate_file_init(pattern)"
612
0
    );
613
614
0
    ramfs_enum * e;
615
616
0
    if (iodev->state == NULL)
617
0
        return NULL;
618
0
    else
619
0
        e = ramfs_enum_new(GETRAMFS(iodev->state));
620
621
0
    if(penum && pattern && e) {
622
0
    memcpy(pattern, pat, patlen);
623
0
    pattern[patlen]=0;
624
625
0
    penum->memory = mem;
626
0
    penum->pattern = pattern;
627
0
    penum->e = e;
628
0
    return (file_enum *)penum;
629
0
    }
630
0
    if (penum) gs_free_object(mem,penum,"ramfs_enum_init(ramfs_enum)");
631
0
    if (pattern)
632
0
    gs_free_object(mem, pattern, "ramfs_enum_init(pattern)");
633
0
    if(e) ramfs_enum_end(e);
634
0
    return NULL;
635
0
}
636
637
static void
638
ram_enumerate_close(gs_memory_t * mem, file_enum *pfen)
639
0
{
640
0
    gsram_enum *penum = (gsram_enum *)pfen;
641
0
    gs_memory_t *mem2 = penum->memory;
642
0
    (void)mem;
643
644
0
    ramfs_enum_end(penum->e);
645
0
    gs_free_object(mem2, penum->pattern, "ramfs_enum_init(pattern)");
646
0
    gs_free_object(mem2, penum, "ramfs_enum_init(ramfs_enum)");
647
0
}
648
649
static uint
650
ram_enumerate_next(gs_memory_t * mem, file_enum *pfen, char *ptr, uint maxlen)
651
0
{
652
0
    gsram_enum *penum = (gsram_enum *)pfen;
653
654
0
    char * filename;
655
0
    while ((filename = ramfs_enum_next(penum->e))) {
656
0
    if (string_match((byte *)filename, strlen(filename),
657
0
        (byte *)penum->pattern,
658
0
        strlen(penum->pattern), 0)) {
659
0
        if (strlen(filename) < maxlen)
660
0
        memcpy(ptr, filename, strlen(filename));
661
0
        return strlen(filename);    /* if > maxlen, caller will detect rangecheck */
662
0
    }
663
0
    }
664
    /* ran off end of list, close the enum */
665
0
    ram_enumerate_close(mem, pfen);
666
0
    return ~(uint)0;
667
0
}
668
669
static int
670
ram_get_params(gx_io_device * iodev, gs_param_list * plist)
671
0
{
672
0
    int code;
673
0
    int i0 = 0, so = 1;
674
0
    bool btrue = true, bfalse = false;
675
0
    ramfs* fs;
676
677
0
    int BlockSize;
678
0
    long Free, LogicalSize;
679
680
0
    if (iodev->state == NULL)
681
0
        return_error(gs_error_ioerror);
682
0
    else
683
0
        fs = GETRAMFS(iodev->state);
684
685
0
    BlockSize = ramfs_blocksize(fs);
686
0
    LogicalSize = MAXBLOCKS;
687
0
    Free = ramfs_blocksfree(fs);
688
689
0
    if (
690
0
    (code = param_write_bool(plist, "HasNames",        &btrue)) < 0 ||
691
0
    (code = param_write_int (plist, "BlockSize",       &BlockSize)) < 0 ||
692
0
    (code = param_write_long(plist, "Free",            &Free)) < 0 ||
693
0
    (code = param_write_int (plist, "InitializeAction",&i0)) < 0 ||
694
0
    (code = param_write_bool(plist, "Mounted",         &btrue)) < 0 ||
695
0
    (code = param_write_bool(plist, "Removable",       &bfalse)) < 0 ||
696
0
    (code = param_write_bool(plist, "Searchable",      &btrue)) < 0 ||
697
0
    (code = param_write_int (plist, "SearchOrder",     &so)) < 0 ||
698
0
    (code = param_write_bool(plist, "Writeable",       &btrue)) < 0 ||
699
0
    (code = param_write_long(plist, "LogicalSize",     &LogicalSize)) < 0
700
0
    )
701
0
    return code;
702
0
    return 0;
703
0
}