Coverage Report

Created: 2022-10-14 11:20

/src/php-src/ext/standard/link.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
   +----------------------------------------------------------------------+
3
   | Copyright (c) The PHP Group                                          |
4
   +----------------------------------------------------------------------+
5
   | This source file is subject to version 3.01 of the PHP license,      |
6
   | that is bundled with this package in the file LICENSE, and is        |
7
   | available through the world-wide-web at the following url:           |
8
   | http://www.php.net/license/3_01.txt                                  |
9
   | If you did not receive a copy of the PHP license and are unable to   |
10
   | obtain it through the world-wide-web, please send a note to          |
11
   | license@php.net so we can mail you a copy immediately.               |
12
   +----------------------------------------------------------------------+
13
   | Author:                                                              |
14
   +----------------------------------------------------------------------+
15
 */
16
17
#include "php.h"
18
#include "php_filestat.h"
19
#include "php_globals.h"
20
21
#if defined(HAVE_SYMLINK) || defined(PHP_WIN32)
22
23
#ifdef PHP_WIN32
24
#include <WinBase.h>
25
#endif
26
27
#include <stdlib.h>
28
#if HAVE_UNISTD_H
29
#include <unistd.h>
30
#endif
31
#ifndef PHP_WIN32
32
#include <sys/stat.h>
33
#endif
34
#include <string.h>
35
#if HAVE_PWD_H
36
#ifdef PHP_WIN32
37
#include "win32/pwd.h"
38
#else
39
#include <pwd.h>
40
#endif
41
#endif
42
#if HAVE_GRP_H
43
#ifdef PHP_WIN32
44
#include "win32/grp.h"
45
#else
46
#include <grp.h>
47
#endif
48
#endif
49
#include <errno.h>
50
#include <ctype.h>
51
52
#include "php_string.h"
53
54
#ifndef VOLUME_NAME_NT
55
#define VOLUME_NAME_NT 0x2
56
#endif
57
58
#ifndef VOLUME_NAME_DOS
59
#define VOLUME_NAME_DOS 0x0
60
#endif
61
62
/* {{{ proto string|false readlink(string filename)
63
   Return the target of a symbolic link */
64
PHP_FUNCTION(readlink)
65
0
{
66
0
  char *link;
67
0
  size_t link_len;
68
0
  char buff[MAXPATHLEN];
69
0
  ssize_t ret;
70
71
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
72
0
    Z_PARAM_PATH(link, link_len)
73
0
  ZEND_PARSE_PARAMETERS_END();
74
75
0
  if (php_check_open_basedir(link)) {
76
0
    RETURN_FALSE;
77
0
  }
78
79
0
  ret = php_sys_readlink(link, buff, MAXPATHLEN-1);
80
81
0
  if (ret == -1) {
82
#ifdef PHP_WIN32
83
    php_error_docref(NULL, E_WARNING, "readlink failed to read the symbolic link (%s), error %d)", link, GetLastError());
84
#else
85
0
    php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
86
0
#endif
87
0
    RETURN_FALSE;
88
0
  }
89
  /* Append NULL to the end of the string */
90
0
  buff[ret] = '\0';
91
92
0
  RETURN_STRINGL(buff, ret);
93
0
}
94
/* }}} */
95
96
/* {{{ proto int|false linkinfo(string filename)
97
   Returns the st_dev field of the UNIX C stat structure describing the link */
98
PHP_FUNCTION(linkinfo)
99
0
{
100
0
  char *link;
101
0
  char *dirname;
102
0
  size_t link_len;
103
0
  zend_stat_t sb;
104
0
  int ret;
105
106
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
107
0
    Z_PARAM_PATH(link, link_len)
108
0
  ZEND_PARSE_PARAMETERS_END();
109
110
0
  dirname = estrndup(link, link_len);
111
0
  php_dirname(dirname, link_len);
112
113
0
  if (php_check_open_basedir(dirname)) {
114
0
    efree(dirname);
115
0
    RETURN_FALSE;
116
0
  }
117
118
0
  ret = VCWD_LSTAT(link, &sb);
119
0
  if (ret == -1) {
120
0
    php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
121
0
    efree(dirname);
122
0
    RETURN_LONG(Z_L(-1));
123
0
  }
124
125
0
  efree(dirname);
126
0
  RETURN_LONG((zend_long) sb.st_dev);
127
0
}
128
/* }}} */
129
130
/* {{{ proto bool symlink(string target, string link)
131
   Create a symbolic link */
132
PHP_FUNCTION(symlink)
133
0
{
134
0
  char *topath, *frompath;
135
0
  size_t topath_len, frompath_len;
136
0
  int ret;
137
0
  char source_p[MAXPATHLEN];
138
0
  char dest_p[MAXPATHLEN];
139
0
  char dirname[MAXPATHLEN];
140
0
  size_t len;
141
142
0
  ZEND_PARSE_PARAMETERS_START(2, 2)
143
0
    Z_PARAM_PATH(topath, topath_len)
144
0
    Z_PARAM_PATH(frompath, frompath_len)
145
0
  ZEND_PARSE_PARAMETERS_END();
146
147
0
  if (!expand_filepath(frompath, source_p)) {
148
0
    php_error_docref(NULL, E_WARNING, "No such file or directory");
149
0
    RETURN_FALSE;
150
0
  }
151
152
0
  memcpy(dirname, source_p, sizeof(source_p));
153
0
  len = php_dirname(dirname, strlen(dirname));
154
155
0
  if (!expand_filepath_ex(topath, dest_p, dirname, len)) {
156
0
    php_error_docref(NULL, E_WARNING, "No such file or directory");
157
0
    RETURN_FALSE;
158
0
  }
159
160
0
  if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY) ||
161
0
    php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY) )
162
0
  {
163
0
    php_error_docref(NULL, E_WARNING, "Unable to symlink to a URL");
164
0
    RETURN_FALSE;
165
0
  }
166
167
0
  if (php_check_open_basedir(dest_p)) {
168
0
    RETURN_FALSE;
169
0
  }
170
171
0
  if (php_check_open_basedir(source_p)) {
172
0
    RETURN_FALSE;
173
0
  }
174
175
  /* For the source, an expanded path must be used (in ZTS an other thread could have changed the CWD).
176
   * For the target the exact string given by the user must be used, relative or not, existing or not.
177
   * The target is relative to the link itself, not to the CWD. */
178
0
  ret = php_sys_symlink(topath, source_p);
179
180
0
  if (ret == -1) {
181
0
    php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
182
0
    RETURN_FALSE;
183
0
  }
184
185
0
  RETURN_TRUE;
186
0
}
187
/* }}} */
188
189
/* {{{ proto bool link(string target, string link)
190
   Create a hard link */
191
PHP_FUNCTION(link)
192
0
{
193
0
  char *topath, *frompath;
194
0
  size_t topath_len, frompath_len;
195
0
  int ret;
196
0
  char source_p[MAXPATHLEN];
197
0
  char dest_p[MAXPATHLEN];
198
199
0
  ZEND_PARSE_PARAMETERS_START(2, 2)
200
0
    Z_PARAM_PATH(topath, topath_len)
201
0
    Z_PARAM_PATH(frompath, frompath_len)
202
0
  ZEND_PARSE_PARAMETERS_END();
203
204
0
  if (!expand_filepath(frompath, source_p) || !expand_filepath(topath, dest_p)) {
205
0
    php_error_docref(NULL, E_WARNING, "No such file or directory");
206
0
    RETURN_FALSE;
207
0
  }
208
209
0
  if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY) ||
210
0
    php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY) )
211
0
  {
212
0
    php_error_docref(NULL, E_WARNING, "Unable to link to a URL");
213
0
    RETURN_FALSE;
214
0
  }
215
216
0
  if (php_check_open_basedir(dest_p)) {
217
0
    RETURN_FALSE;
218
0
  }
219
220
0
  if (php_check_open_basedir(source_p)) {
221
0
    RETURN_FALSE;
222
0
  }
223
224
0
#ifndef ZTS
225
0
  ret = php_sys_link(topath, frompath);
226
#else
227
  ret = php_sys_link(dest_p, source_p);
228
#endif
229
0
  if (ret == -1) {
230
0
    php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
231
0
    RETURN_FALSE;
232
0
  }
233
234
0
  RETURN_TRUE;
235
0
}
236
/* }}} */
237
238
#endif