1 /* Copyright (C) 2001-2006 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, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 
14 /* $Id: gsfname.c 8022 2007-06-05 22:23:38Z giles $ */
15 /* File name utilities */
16 #include "memory_.h"
17 #include "gserror.h"
18 #include "gserrors.h"
19 #include "gsmemory.h"
20 #include "gstypes.h"
21 #include "gsfname.h"
22 #include "gxiodev.h"
23 
24 /* Parse a file name into device and individual name. */
25 /* The device may be NULL, or the name may be NULL, but not both. */
26 /* According to the Adobe documentation, %device and %device% */
27 /* are equivalent; both return name==NULL. */
28 int
gs_parse_file_name(gs_parsed_file_name_t * pfn,const char * pname,uint len)29 gs_parse_file_name(gs_parsed_file_name_t * pfn, const char *pname, uint len)
30 {
31     uint dlen;
32     const char *pdelim;
33     gx_io_device *iodev;
34 
35     if (len == 0)
36 	return_error(gs_error_undefinedfilename); /* null name not allowed */
37     if (pname[0] != '%') {	/* no device */
38 	pfn->memory = 0;
39 	pfn->iodev = NULL;
40 	pfn->fname = pname;
41 	pfn->len = len;
42 	return 0;
43     }
44     pdelim = memchr(pname + 1, '%', len - 1);
45     if (pdelim == NULL)		/* %device */
46 	dlen = len;
47     else if (pdelim[1] == 0) {	/* %device% */
48 	pdelim = NULL;
49 	dlen = len;
50     } else {
51 	dlen = pdelim - pname;
52 	pdelim++, len--;
53     }
54     iodev = gs_findiodevice((const byte *)pname, dlen);
55     if (iodev == 0)
56 	return_error(gs_error_undefinedfilename);
57     pfn->memory = 0;
58     pfn->iodev = iodev;
59     pfn->fname = pdelim;
60     pfn->len = len - dlen;
61     return 0;
62 }
63 
64 /* Parse a real (non-device) file name and convert to a C string. */
65 int
gs_parse_real_file_name(gs_parsed_file_name_t * pfn,const char * pname,uint len,gs_memory_t * mem,client_name_t cname)66 gs_parse_real_file_name(gs_parsed_file_name_t * pfn, const char *pname,
67 			uint len, gs_memory_t *mem, client_name_t cname)
68 {
69     int code = gs_parse_file_name(pfn, pname, len);
70 
71     if (code < 0)
72 	return code;
73     if (pfn->len == 0)  /* device only */
74 	return_error(gs_error_undefinedfilename); /* for CET 23-23.ps */
75     return gs_terminate_file_name(pfn, mem, cname);
76 }
77 
78 /* Convert a file name to a C string by adding a null terminator. */
79 int
gs_terminate_file_name(gs_parsed_file_name_t * pfn,gs_memory_t * mem,client_name_t cname)80 gs_terminate_file_name(gs_parsed_file_name_t * pfn, gs_memory_t *mem,
81 		       client_name_t cname)
82 {
83     uint len = pfn->len;
84     char *fname;
85 
86     if (pfn->iodev == NULL)	/* no device */
87 	pfn->iodev = iodev_default;
88     if (pfn->memory)
89 	return 0;		/* already copied */
90     /* Copy the file name to a C string. */
91     fname = (char *)gs_alloc_string(mem, len + 1, cname);
92     if (fname == 0)
93 	return_error(gs_error_VMerror);
94     memcpy(fname, pfn->fname, len);
95     fname[len] = 0;
96     pfn->memory = mem;
97     pfn->fname = fname;
98     pfn->len = len + 1;		/* null terminator */
99     return 0;
100 }
101 
102 /* Free a file name that was copied to a C string. */
103 void
gs_free_file_name(gs_parsed_file_name_t * pfn,client_name_t cname)104 gs_free_file_name(gs_parsed_file_name_t * pfn, client_name_t cname)
105 {
106     if (pfn->fname != 0)
107 	gs_free_const_string(pfn->memory, (const byte *)pfn->fname, pfn->len,
108 			     cname);
109 }
110