Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gdevpipe.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 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
17
/* %pipe% IODevice */
18
#include "errno_.h"
19
#include "pipe_.h"
20
#include "stdio_.h"
21
#include "string_.h"
22
#include "gserrors.h"
23
#include "gstypes.h"
24
#include "gsmemory.h"   /* for gxiodev.h */
25
#include "gxiodev.h"
26
27
/* The file device procedures */
28
29
static int
30
do_pclose(FILE *file)
31
0
{
32
#ifdef GS_NO_FILESYSTEM
33
    return gs_error_ok;
34
#else
35
0
    int status = pclose(file);
36
0
    if (status < 0 || status > 0)
37
0
      return_error(gs_error_ioerror);
38
39
0
    return gs_error_ok;
40
0
#endif
41
0
}
42
43
static int
44
fs_file_open_pipe(const gs_memory_t *mem, void *secret, const char *fname, char *rfname, const char *mode, gp_file **file)
45
0
{
46
0
    *file = gp_file_FILE_alloc(mem);
47
0
    if (*file == NULL)
48
0
        return gs_error_VMerror;
49
50
0
    errno = 0;
51
    /*
52
     * The OSF/1 1.3 library doesn't include const in the
53
     * prototype for popen, so we have to break const here.
54
     */
55
0
    if (gp_file_FILE_set(*file, popen((char *)fname, (char *)mode), do_pclose)) {
56
0
        *file = NULL;
57
0
        return_error(gs_fopen_errno_to_code(errno));
58
0
    }
59
60
0
    if (rfname != NULL && rfname != fname)
61
0
        strcpy(rfname, fname);
62
63
0
    return 0;
64
0
}
65
66
static int
67
pipe_fopen(gx_io_device * iodev, const char *fname, const char *access,
68
           gp_file ** pfile, char *rfname, uint rnamelen, gs_memory_t *mem)
69
0
{
70
#ifdef GS_NO_FILESYSTEM
71
    return 0;
72
#else
73
0
    gs_lib_ctx_t *ctx = mem->gs_lib_ctx;
74
0
    gs_fs_list_t *fs = ctx->core->fs;
75
    /* The pipe device can be reached in two ways, explicltly with %pipe%
76
       or implicitly with "|", so we have to check for both
77
     */
78
0
    char f[gp_file_name_sizeof];
79
0
    const char *pipestr = "|";
80
0
    const size_t pipestrlen = strlen(pipestr);
81
0
    const size_t preflen = strlen(iodev->dname);
82
0
    const size_t nlen = strlen(fname);
83
0
    int code1;
84
85
0
    if (preflen + nlen >= gp_file_name_sizeof)
86
0
        return_error(gs_error_invalidaccess);
87
88
0
    memcpy(f, iodev->dname, preflen);
89
0
    memcpy(f + preflen, fname, nlen + 1);
90
91
0
    code1 = gp_validate_path(mem, f, access);
92
93
0
    memcpy(f, pipestr, pipestrlen);
94
0
    memcpy(f + pipestrlen, fname, nlen + 1);
95
96
0
    if (code1 != 0 && gp_validate_path(mem, f, access) != 0 )
97
0
        return gs_error_invalidfileaccess;
98
99
    /*
100
     * Some platforms allow opening a pipe with a '+' in the access
101
     * mode, even though pipes are not positionable.  Detect this here.
102
     */
103
0
    if (strchr(access, '+'))
104
0
        return_error(gs_error_invalidfileaccess);
105
106
0
    *pfile = NULL;
107
0
    for (fs = ctx->core->fs; fs != NULL; fs = fs->next)
108
0
    {
109
0
        int code = 0;
110
0
        if (fs->fs.open_pipe)
111
0
            code = fs->fs.open_pipe(mem, fs->secret, fname, rfname, access, pfile);
112
0
        if (code < 0)
113
0
            return code;
114
0
        if (*pfile != NULL)
115
0
            break;
116
0
    }
117
118
0
    return 0;
119
0
#endif
120
0
}
121
122
static int
123
pipe_fclose(gx_io_device * iodev, gp_file * file)
124
0
{
125
#ifdef GS_NO_FILESYSTEM
126
    return 0;
127
#else
128
0
    return gp_fclose(file);
129
0
#endif
130
0
}
131
132
static int
133
pipe_init(gx_io_device * iodev, gs_memory_t * mem)
134
162k
{
135
162k
    gs_fs_list_t *fs = mem->gs_lib_ctx->core->fs;
136
137
162k
    while (fs->next)
138
0
        fs = fs->next;
139
140
    /* Last one is out file device */
141
162k
    fs->fs.open_pipe = fs_file_open_pipe;
142
143
162k
    return 0;
144
162k
}
145
146
/* The pipe IODevice */
147
const gx_io_device gs_iodev_pipe = {
148
    "%pipe%", "Special",
149
    {pipe_init, iodev_no_finit, iodev_no_open_device,
150
     NULL /*iodev_os_open_file */ , pipe_fopen, pipe_fclose,
151
     iodev_no_delete_file, iodev_no_rename_file, iodev_no_file_status,
152
     iodev_no_enumerate_files, NULL, NULL,
153
     iodev_no_get_params, iodev_no_put_params
154
    },
155
    NULL,
156
    NULL
157
};
158