/src/ghostpdl/base/gsioram.c
Line | Count | Source |
1 | | /* Copyright (C) 2001-2025 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_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 | 385k | #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_ptrs2(st_gsram_enum, struct gsram_enum_s, "gsram_enum", |
90 | | gsram_enum_enum_ptrs, gsram_enum_reloc_ptrs, pattern, 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 | 192k | #define MAXBLOCKS 2000000 |
95 | | |
96 | 0 | #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 |
116 | 0 | ramfs_errno_to_code(int error_number) { |
117 | 0 | switch (error_number) { |
118 | 0 | case RAMFS_NOTFOUND: |
119 | 0 | return_error(gs_error_undefinedfilename); |
120 | 0 | case RAMFS_NOACCESS: |
121 | 0 | return_error(gs_error_invalidfileaccess); |
122 | 0 | case RAMFS_NOMEM: |
123 | 0 | return_error(gs_error_VMerror); |
124 | 0 | case RAMFS_BADRANGE: |
125 | 0 | return_error(gs_error_rangecheck); |
126 | 0 | case RAMFS_DELETEOPENFILE: |
127 | 0 | return_error(gs_error_ioerror); |
128 | | /* just in case */ |
129 | 0 | default: |
130 | 0 | return_error(gs_error_ioerror); |
131 | 0 | } |
132 | 0 | } |
133 | | |
134 | | static void |
135 | | sread_ram(register stream * s, ramhandle * file, byte * buf, uint len), |
136 | | swrite_ram(register stream * s, ramhandle * file, byte * buf, uint len), |
137 | | sappend_ram(register stream * s, ramhandle * file, byte * buf, uint len); |
138 | | |
139 | | static int |
140 | | ram_open_file(gx_io_device * iodev, const char *fname, uint len, |
141 | | const char *file_access, stream ** ps, gs_memory_t * mem) |
142 | 0 | { |
143 | 0 | int code = 0; |
144 | 0 | ramhandle * file; |
145 | 0 | char fmode[4]; /* r/w/a, [+], [b], null */ |
146 | 0 | int openmode=RAMFS_READ; |
147 | 0 | ramfs * fs; |
148 | 0 | char * namestr = NULL; |
149 | | |
150 | | /* Is there a more efficient way to do this? */ |
151 | 0 | namestr = (char *)gs_alloc_bytes(mem, len + 1, "temporary filename string"); |
152 | 0 | if(!namestr) |
153 | 0 | return_error(gs_error_VMerror); |
154 | 0 | strncpy(namestr,fname,len); |
155 | 0 | namestr[len] = 0; |
156 | | |
157 | | /* Make sure iodev is valid, and we have initialised the RAM file system (state != NULL) */ |
158 | 0 | if (iodev == NULL || iodev->state == NULL) {/*iodev = iodev_default;*/ |
159 | 0 | gs_free_object(mem, namestr, "free temporary filename string"); |
160 | 0 | return gs_note_error(gs_error_invalidaccess); |
161 | 0 | } |
162 | 0 | fs = GETRAMFS(iodev->state); |
163 | 0 | code = file_prepare_stream(fname, len, file_access, DEFAULT_BUFFER_SIZE, |
164 | 0 | ps, fmode, mem |
165 | 0 | ); |
166 | 0 | if (code < 0) goto error; |
167 | 0 | if (fname == 0) { |
168 | 0 | gs_free_object(mem, namestr, "free temporary filename string"); |
169 | 0 | return 0; |
170 | 0 | } |
171 | | |
172 | 0 | switch (fmode[0]) { |
173 | 0 | case 'a': |
174 | 0 | openmode = RAMFS_WRITE | RAMFS_APPEND; |
175 | 0 | break; |
176 | 0 | case 'r': |
177 | 0 | openmode = RAMFS_READ; |
178 | 0 | if (fmode[1] == '+') |
179 | 0 | openmode |= RAMFS_WRITE; |
180 | 0 | break; |
181 | 0 | case 'w': |
182 | 0 | openmode |= RAMFS_WRITE | RAMFS_TRUNC | RAMFS_CREATE; |
183 | 0 | if (fmode[1] == '+') |
184 | 0 | openmode |= RAMFS_READ; |
185 | 0 | } |
186 | | |
187 | | /* For now, we cheat here in the same way that sfxstdio.c et al cheat - |
188 | | append mode is faked by opening in write mode and seeking to EOF just |
189 | | once. This is different from unix semantics, which seeks atomically |
190 | | before each write, and is actually useful as a distinct mode. */ |
191 | | /* if (fmode[0] == 'a') openmode |= RAMFS_APPEND; */ |
192 | | |
193 | 0 | file = ramfs_open(mem, fs,namestr,openmode); |
194 | 0 | if(!file) { code = ramfs_errno_to_code(ramfs_error(fs)); goto error; } |
195 | | |
196 | 0 | switch (fmode[0]) { |
197 | 0 | case 'a': |
198 | 0 | sappend_ram(*ps, file, (*ps)->cbuf, (*ps)->bsize); |
199 | 0 | break; |
200 | 0 | case 'r': |
201 | 0 | sread_ram(*ps, file, (*ps)->cbuf, (*ps)->bsize); |
202 | 0 | break; |
203 | 0 | case 'w': |
204 | 0 | swrite_ram(*ps, file, (*ps)->cbuf, (*ps)->bsize); |
205 | 0 | } |
206 | 0 | if (fmode[1] == '+') { |
207 | 0 | (*ps)->modes = (*ps)->file_modes |= s_mode_read | s_mode_write; |
208 | 0 | } |
209 | 0 | (*ps)->save_close = (*ps)->procs.close; |
210 | 0 | (*ps)->procs.close = file_close_file; |
211 | 0 | error: |
212 | 0 | gs_free_object(mem, namestr, "free temporary filename string"); |
213 | | /* XXX free stream stuff? */ |
214 | 0 | return code; |
215 | 0 | } |
216 | | |
217 | | /* Initialize a stream for reading an OS file. */ |
218 | | static void |
219 | | sread_ram(register stream * s, ramhandle * file, byte * buf, uint len) |
220 | 0 | { |
221 | 0 | static const stream_procs p = { |
222 | 0 | s_ram_available, s_ram_read_seek, s_std_read_reset, |
223 | 0 | s_std_read_flush, s_ram_read_close, s_ram_read_process, |
224 | 0 | s_ram_switch |
225 | 0 | }; |
226 | |
|
227 | 0 | s_std_init(s, buf, len, &p,s_mode_read + s_mode_seek); |
228 | 0 | s->file = (gp_file *)file; |
229 | 0 | s->file_modes = s->modes; |
230 | 0 | s->file_offset = 0; |
231 | 0 | ramfile_seek(file, 0, RAMFS_SEEK_END); |
232 | 0 | s->file_limit = ramfile_tell(file); |
233 | 0 | ramfile_seek(file, 0, RAMFS_SEEK_SET); |
234 | 0 | } |
235 | | |
236 | | /* Procedures for reading from a file */ |
237 | | static int |
238 | | s_ram_available(register stream * s, gs_offset_t *pl) |
239 | 0 | { |
240 | 0 | long max_avail = s->file_limit - stell(s); |
241 | |
|
242 | 0 | *pl = max_avail; |
243 | 0 | if(*pl == 0 && ramfile_eof((ramhandle*)s->file)) |
244 | 0 | *pl = -1; /* EOF */ |
245 | 0 | return 0; |
246 | 0 | } |
247 | | |
248 | | static int |
249 | | s_ram_read_seek(register stream * s, gs_offset_t pos) |
250 | 0 | { |
251 | 0 | uint end = s->cursor.r.limit - s->cbuf + 1; |
252 | 0 | long offset = pos - s->position; |
253 | |
|
254 | 0 | if (offset >= 0 && offset <= end) { /* Staying within the same buffer */ |
255 | 0 | s->cursor.r.ptr = s->cbuf + offset - 1; |
256 | 0 | return 0; |
257 | 0 | } |
258 | | |
259 | 0 | if (pos < 0 || pos > s->file_limit || s->file == NULL || |
260 | 0 | ramfile_seek((ramhandle*)s->file, s->file_offset + pos, RAMFS_SEEK_SET) != 0) |
261 | 0 | return ERRC; |
262 | | |
263 | 0 | s->cursor.r.ptr = s->cursor.r.limit = s->cbuf - 1; |
264 | 0 | s->end_status = 0; |
265 | 0 | s->position = pos; |
266 | 0 | return 0; |
267 | 0 | } |
268 | | static int |
269 | | s_ram_read_close(stream * s) |
270 | 0 | { |
271 | 0 | ramhandle *file = (ramhandle*)s->file; |
272 | |
|
273 | 0 | if (file != 0) { |
274 | 0 | s->file = 0; |
275 | 0 | ramfile_close(file); |
276 | 0 | } |
277 | 0 | return 0; |
278 | 0 | } |
279 | | |
280 | | /* |
281 | | * Process a buffer for a file reading stream. |
282 | | * This is the first stream in the pipeline, so pr is irrelevant. |
283 | | */ |
284 | | static int |
285 | | s_ram_read_process(stream_state * st, stream_cursor_read * ignore_pr, |
286 | | stream_cursor_write * pw, bool last) |
287 | 0 | { |
288 | 0 | stream *s = (stream *)st; /* no separate state */ |
289 | 0 | ramhandle *file = (ramhandle*)s->file; |
290 | 0 | uint max_count = pw->limit - pw->ptr; |
291 | 0 | int status = 1; |
292 | 0 | int count; |
293 | |
|
294 | 0 | if (s->file_limit < S_FILE_LIMIT_MAX) { |
295 | 0 | long limit_count = s->file_offset + s->file_limit - |
296 | 0 | ramfile_tell(file); |
297 | |
|
298 | 0 | if (max_count > limit_count) |
299 | 0 | max_count = limit_count, status = EOFC; |
300 | 0 | } |
301 | 0 | count = ramfile_read(file,pw->ptr + 1, max_count); |
302 | 0 | if (count < 0) return ERRC; |
303 | 0 | pw->ptr += count; |
304 | | /* process_interrupts(s->memory); */ |
305 | 0 | return ramfile_eof(file) ? EOFC : status; |
306 | 0 | } |
307 | | |
308 | | /* ------ File writing ------ */ |
309 | | |
310 | | /* Initialize a stream for writing a file. */ |
311 | | static void |
312 | | swrite_ram(register stream * s, ramhandle * file, byte * buf, uint len) |
313 | 0 | { |
314 | 0 | static const stream_procs p = { |
315 | 0 | s_std_noavailable, s_ram_write_seek, s_std_write_reset, |
316 | 0 | s_ram_write_flush, s_ram_write_close, s_ram_write_process, |
317 | 0 | s_ram_switch |
318 | 0 | }; |
319 | |
|
320 | 0 | s_std_init(s, buf, len, &p, s_mode_write + s_mode_seek); |
321 | 0 | s->file = (gp_file *)file; |
322 | 0 | s->file_modes = s->modes; |
323 | 0 | s->file_offset = 0; /* in case we switch to reading later */ |
324 | 0 | s->file_limit = S_FILE_LIMIT_MAX; |
325 | 0 | } |
326 | | |
327 | | /* Initialize for appending to a file. */ |
328 | | static void |
329 | | sappend_ram(register stream * s, ramhandle * file, byte * buf, uint len) |
330 | 0 | { |
331 | 0 | swrite_ram(s, file, buf, len); |
332 | 0 | s->modes = s_mode_write + s_mode_append; /* no seek */ |
333 | 0 | s->file_modes = s->modes; |
334 | 0 | ramfile_seek(file,0,RAMFS_SEEK_END); |
335 | 0 | s->position = ramfile_tell(file); |
336 | 0 | } |
337 | | |
338 | | /* Procedures for writing on a file */ |
339 | | static int |
340 | | s_ram_write_seek(stream * s, gs_offset_t pos) |
341 | 0 | { |
342 | | /* We must flush the buffer to reposition. */ |
343 | 0 | int code = sflush(s); |
344 | |
|
345 | 0 | if (code < 0) return code; |
346 | 0 | if (pos < 0 || ramfile_seek((ramhandle*)s->file, pos, RAMFS_SEEK_SET) != 0) |
347 | 0 | return ERRC; |
348 | 0 | s->position = pos; |
349 | 0 | return 0; |
350 | 0 | } |
351 | | |
352 | | static int |
353 | | s_ram_write_flush(register stream * s) |
354 | 0 | { |
355 | 0 | int result = s_process_write_buf(s, false); |
356 | 0 | return result; |
357 | 0 | } |
358 | | |
359 | | static int |
360 | | s_ram_write_close(register stream * s) |
361 | 0 | { |
362 | 0 | s_process_write_buf(s, true); |
363 | 0 | return s_ram_read_close(s); |
364 | 0 | } |
365 | | |
366 | | /* |
367 | | * Process a buffer for a file writing stream. |
368 | | * This is the last stream in the pipeline, so pw is irrelevant. |
369 | | */ |
370 | | static int |
371 | | s_ram_write_process(stream_state * st, stream_cursor_read * pr, |
372 | | stream_cursor_write * ignore_pw, bool last) |
373 | 0 | { |
374 | 0 | uint count = pr->limit - pr->ptr; |
375 | |
|
376 | 0 | ramhandle *file = (ramhandle*)((stream *) st)->file; |
377 | 0 | int written = ramfile_write(file,pr->ptr + 1, count); |
378 | |
|
379 | 0 | if (written < 0) return ERRC; |
380 | 0 | pr->ptr += written; |
381 | 0 | return 0; |
382 | 0 | } |
383 | | |
384 | | static int |
385 | | s_ram_switch(stream * s, bool writing) |
386 | 0 | { |
387 | 0 | uint modes = s->file_modes; |
388 | 0 | ramhandle *file = (ramhandle*)s->file; |
389 | 0 | long pos; |
390 | |
|
391 | 0 | if (writing) { |
392 | 0 | if (!(s->file_modes & s_mode_write)) return ERRC; |
393 | 0 | pos = stell(s); |
394 | 0 | ramfile_seek(file, pos, RAMFS_SEEK_SET); |
395 | 0 | if (modes & s_mode_append) { |
396 | 0 | sappend_ram(s, file, s->cbuf, s->cbsize); /* sets position */ |
397 | 0 | } else { |
398 | 0 | swrite_ram(s, file, s->cbuf, s->cbsize); |
399 | 0 | s->position = pos; |
400 | 0 | } |
401 | 0 | s->modes = modes; |
402 | 0 | } else { |
403 | 0 | if (!(s->file_modes & s_mode_read)) return ERRC; |
404 | 0 | pos = stell(s); |
405 | 0 | if (sflush(s) < 0) return ERRC; |
406 | 0 | sread_ram(s, file, s->cbuf, s->cbsize); |
407 | 0 | s->modes |= modes & s_mode_append; /* don't lose append info */ |
408 | 0 | s->position = pos; |
409 | 0 | } |
410 | 0 | s->file_modes = modes; |
411 | 0 | return 0; |
412 | 0 | } |
413 | | |
414 | | |
415 | | /* gx_io_device stuff */ |
416 | | |
417 | | static int |
418 | | iodev_ram_init(gx_io_device * iodev, gs_memory_t * mem) |
419 | 192k | { |
420 | 192k | ramfs* fs = ramfs_new(mem, MAXBLOCKS); |
421 | 192k | ramfs_state* state = gs_alloc_struct(mem, ramfs_state, &st_ramfs_state, |
422 | 192k | "ramfs_init(state)" |
423 | 192k | ); |
424 | 192k | if (fs && state) { |
425 | 192k | state->fs = fs; |
426 | 192k | state->memory = mem; |
427 | 192k | iodev->state = state; |
428 | 192k | return 0; |
429 | 192k | } |
430 | 0 | if(fs) ramfs_destroy(mem, fs); |
431 | 0 | if(state) gs_free_object(mem,state,"iodev_ram_init(state)"); |
432 | 0 | return_error(gs_error_VMerror); |
433 | 192k | } |
434 | | |
435 | | static void |
436 | | iodev_ram_finit(gx_io_device * iodev, gs_memory_t * mem) |
437 | 58.8k | { |
438 | 58.8k | ramfs_state *state = (ramfs_state *)iodev->state; |
439 | 58.8k | if (state != NULL) |
440 | 58.8k | { |
441 | 58.8k | iodev->state = NULL; |
442 | 58.8k | gs_free_object(state->memory, state, "iodev_ram_finit"); |
443 | 58.8k | } |
444 | 58.8k | return; |
445 | 58.8k | } |
446 | | |
447 | | static void |
448 | | ram_finalize(const gs_memory_t *memory, void * vptr) |
449 | 192k | { |
450 | 192k | ramfs* fs = GETRAMFS((ramfs_state*)vptr); |
451 | 192k | ramfs_destroy((gs_memory_t *)memory, fs); |
452 | 192k | GETRAMFS((ramfs_state*)vptr) = NULL; |
453 | 192k | } |
454 | | |
455 | | static int |
456 | | ram_delete(gx_io_device * iodev, const char *fname) |
457 | 0 | { |
458 | 0 | ramfs* fs; |
459 | |
|
460 | 0 | if (iodev->state == NULL) |
461 | 0 | return_error(gs_error_ioerror); |
462 | 0 | else |
463 | 0 | fs = GETRAMFS(iodev->state); |
464 | | |
465 | 0 | if(ramfs_unlink(fs,fname)!=0) { |
466 | 0 | return_error(ramfs_errno_to_code(ramfs_error(fs))); |
467 | 0 | } |
468 | 0 | return 0; |
469 | 0 | } |
470 | | |
471 | | static int |
472 | | ram_rename(gx_io_device * iodev, const char *from, const char *to) |
473 | 0 | { |
474 | 0 | ramfs* fs; |
475 | |
|
476 | 0 | if (iodev->state == NULL) |
477 | 0 | return_error(gs_error_ioerror); |
478 | 0 | else |
479 | 0 | fs = GETRAMFS(iodev->state); |
480 | | |
481 | 0 | if(ramfs_rename(fs,from,to)!=0) { |
482 | 0 | return_error(ramfs_errno_to_code(ramfs_error(fs))); |
483 | 0 | } |
484 | 0 | return 0; |
485 | 0 | } |
486 | | |
487 | | static int |
488 | | ram_status(gx_io_device * iodev, const char *fname, struct stat *pstat) |
489 | 0 | { |
490 | 0 | ramhandle * f; |
491 | 0 | ramfs* fs; |
492 | |
|
493 | 0 | if (iodev->state == NULL) |
494 | 0 | return_error(gs_error_ioerror); |
495 | 0 | else |
496 | 0 | fs = GETRAMFS(iodev->state); |
497 | | |
498 | 0 | f = ramfs_open(((ramfs_state *)iodev->state)->memory, fs,fname,RAMFS_READ); |
499 | 0 | if(!f) return_error(ramfs_errno_to_code(ramfs_error(fs))); |
500 | | |
501 | 0 | memset(pstat, 0, sizeof(*pstat)); |
502 | 0 | pstat->st_size = ramfile_size(f); |
503 | | /* The Windows definition of struct stat doesn't include a st_blocks member |
504 | | pstat->st_blocks = (pstat->st_size+blocksize-1)/blocksize;*/ |
505 | | /* XXX set mtime & ctime */ |
506 | 0 | ramfile_close(f); |
507 | 0 | return 0; |
508 | 0 | } |
509 | | |
510 | | static file_enum * |
511 | | ram_enumerate_init(gs_memory_t * mem, gx_io_device *iodev, const char *pat, |
512 | | uint patlen) |
513 | 0 | { |
514 | 0 | gsram_enum * penum = gs_alloc_struct( |
515 | 0 | mem, gsram_enum, &st_gsram_enum, |
516 | 0 | "ram_enumerate_files_init(file_enum)" |
517 | 0 | ); |
518 | 0 | char *pattern = (char *)gs_alloc_bytes( |
519 | 0 | mem, patlen+1, "ram_enumerate_file_init(pattern)" |
520 | 0 | ); |
521 | |
|
522 | 0 | ramfs_enum * e; |
523 | |
|
524 | 0 | if (iodev->state == NULL) |
525 | 0 | return NULL; |
526 | 0 | else |
527 | 0 | e = ramfs_enum_new(GETRAMFS(iodev->state)); |
528 | | |
529 | 0 | if(penum && pattern && e) { |
530 | 0 | memcpy(pattern, pat, patlen); |
531 | 0 | pattern[patlen]=0; |
532 | |
|
533 | 0 | penum->memory = mem; |
534 | 0 | penum->pattern = pattern; |
535 | 0 | penum->e = e; |
536 | 0 | return (file_enum *)penum; |
537 | 0 | } |
538 | 0 | if (penum) gs_free_object(mem,penum,"ramfs_enum_init(ramfs_enum)"); |
539 | 0 | if (pattern) |
540 | 0 | gs_free_object(mem, pattern, "ramfs_enum_init(pattern)"); |
541 | 0 | if(e) ramfs_enum_end(e); |
542 | 0 | return NULL; |
543 | 0 | } |
544 | | |
545 | | static void |
546 | | ram_enumerate_close(gs_memory_t * mem, file_enum *pfen) |
547 | 0 | { |
548 | 0 | gsram_enum *penum = (gsram_enum *)pfen; |
549 | 0 | gs_memory_t *mem2 = penum->memory; |
550 | 0 | (void)mem; |
551 | |
|
552 | 0 | ramfs_enum_end(penum->e); |
553 | 0 | gs_free_object(mem2, penum->pattern, "ramfs_enum_init(pattern)"); |
554 | 0 | gs_free_object(mem2, penum, "ramfs_enum_init(ramfs_enum)"); |
555 | 0 | } |
556 | | |
557 | | static uint |
558 | | ram_enumerate_next(gs_memory_t * mem, file_enum *pfen, char *ptr, uint maxlen) |
559 | 0 | { |
560 | 0 | gsram_enum *penum = (gsram_enum *)pfen; |
561 | |
|
562 | 0 | char * filename; |
563 | 0 | while ((filename = ramfs_enum_next(penum->e))) { |
564 | 0 | if (string_match((byte *)filename, strlen(filename), |
565 | 0 | (byte *)penum->pattern, |
566 | 0 | strlen(penum->pattern), 0)) { |
567 | 0 | if (strlen(filename) < maxlen) |
568 | 0 | memcpy(ptr, filename, strlen(filename)); |
569 | 0 | return strlen(filename); /* if > maxlen, caller will detect rangecheck */ |
570 | 0 | } |
571 | 0 | } |
572 | | /* ran off end of list, close the enum */ |
573 | 0 | ram_enumerate_close(mem, pfen); |
574 | 0 | return ~(uint)0; |
575 | 0 | } |
576 | | |
577 | | static int |
578 | | ram_get_params(gx_io_device * iodev, gs_param_list * plist) |
579 | 0 | { |
580 | 0 | int code; |
581 | 0 | int i0 = 0, so = 1; |
582 | 0 | bool btrue = true, bfalse = false; |
583 | 0 | ramfs* fs; |
584 | |
|
585 | 0 | int BlockSize; |
586 | 0 | long Free, LogicalSize; |
587 | |
|
588 | 0 | if (iodev->state == NULL) |
589 | 0 | return_error(gs_error_ioerror); |
590 | 0 | else |
591 | 0 | fs = GETRAMFS(iodev->state); |
592 | | |
593 | 0 | BlockSize = ramfs_blocksize(fs); |
594 | 0 | LogicalSize = MAXBLOCKS; |
595 | 0 | Free = ramfs_blocksfree(fs); |
596 | |
|
597 | 0 | if ( |
598 | 0 | (code = param_write_bool(plist, "HasNames", &btrue)) < 0 || |
599 | 0 | (code = param_write_int (plist, "BlockSize", &BlockSize)) < 0 || |
600 | 0 | (code = param_write_long(plist, "Free", &Free)) < 0 || |
601 | 0 | (code = param_write_int (plist, "InitializeAction",&i0)) < 0 || |
602 | 0 | (code = param_write_bool(plist, "Mounted", &btrue)) < 0 || |
603 | 0 | (code = param_write_bool(plist, "Removable", &bfalse)) < 0 || |
604 | 0 | (code = param_write_bool(plist, "Searchable", &btrue)) < 0 || |
605 | 0 | (code = param_write_int (plist, "SearchOrder", &so)) < 0 || |
606 | 0 | (code = param_write_bool(plist, "Writeable", &btrue)) < 0 || |
607 | 0 | (code = param_write_long(plist, "LogicalSize", &LogicalSize)) < 0 |
608 | 0 | ) |
609 | 0 | return code; |
610 | 0 | return 0; |
611 | 0 | } |