PageRenderTime 55ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/php-pecl-ssh2-0.11.3/ssh2-0.11.3/ssh2_sftp.c

#
C | 856 lines | 573 code | 154 blank | 129 comment | 99 complexity | 18f51ab86b10a5761da04ec3711bbef6 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 4 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2006 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.02 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available at through the world-wide-web at |
  10. | http://www.php.net/license/2_02.txt. |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Sara Golemon <pollita@php.net> |
  16. +----------------------------------------------------------------------+
  17. $Id: ssh2_sftp.c 317118 2011-09-21 19:05:21Z bjori $
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include "php.h"
  23. #include "php_ssh2.h"
  24. #include "ext/standard/php_string.h"
  25. /* *************************
  26. * Resource Housekeeping *
  27. ************************* */
  28. void php_ssh2_sftp_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
  29. {
  30. php_ssh2_sftp_data *data = (php_ssh2_sftp_data*)rsrc->ptr;
  31. if (!data) {
  32. return;
  33. }
  34. libssh2_sftp_shutdown(data->sftp);
  35. zend_list_delete(data->session_rsrcid);
  36. efree(data);
  37. }
  38. /* *****************
  39. * SFTP File Ops *
  40. ***************** */
  41. inline unsigned long php_ssh2_parse_fopen_modes(char *openmode) {
  42. unsigned long flags = 0;
  43. if (strchr(openmode, 'a')) {
  44. flags |= LIBSSH2_FXF_APPEND;
  45. }
  46. if (strchr(openmode, 'w')) {
  47. flags |= LIBSSH2_FXF_WRITE | LIBSSH2_FXF_TRUNC | LIBSSH2_FXF_CREAT;
  48. }
  49. if (strchr(openmode, 'r')) {
  50. flags |= LIBSSH2_FXF_READ;
  51. }
  52. if (strchr(openmode, '+')) {
  53. flags |= LIBSSH2_FXF_READ | LIBSSH2_FXF_WRITE;
  54. }
  55. if (strchr(openmode, 'x')) {
  56. flags |= LIBSSH2_FXF_WRITE | LIBSSH2_FXF_TRUNC | LIBSSH2_FXF_EXCL | LIBSSH2_FXF_CREAT;
  57. }
  58. return flags;
  59. }
  60. inline int php_ssh2_sftp_attr2ssb(php_stream_statbuf *ssb, LIBSSH2_SFTP_ATTRIBUTES *attrs)
  61. {
  62. memset(ssb, 0, sizeof(php_stream_statbuf));
  63. if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
  64. ssb->sb.st_size = attrs->filesize;
  65. }
  66. if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
  67. ssb->sb.st_uid = attrs->uid;
  68. ssb->sb.st_gid = attrs->gid;
  69. }
  70. if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
  71. ssb->sb.st_mode = attrs->permissions;
  72. }
  73. if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
  74. ssb->sb.st_atime = attrs->atime;
  75. ssb->sb.st_mtime = attrs->mtime;
  76. }
  77. return 0;
  78. }
  79. typedef struct _php_ssh2_sftp_handle_data {
  80. LIBSSH2_SFTP_HANDLE *handle;
  81. long sftp_rsrcid;
  82. } php_ssh2_sftp_handle_data;
  83. /* {{{ php_ssh2_sftp_stream_write
  84. */
  85. static size_t php_ssh2_sftp_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
  86. {
  87. php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
  88. ssize_t bytes_written;
  89. bytes_written = libssh2_sftp_write(data->handle, buf, count);
  90. return (size_t)(bytes_written<0 ? 0 : bytes_written);
  91. }
  92. /* }}} */
  93. /* {{{ php_ssh2_sftp_stream_read
  94. */
  95. static size_t php_ssh2_sftp_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
  96. {
  97. php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
  98. ssize_t bytes_read;
  99. bytes_read = libssh2_sftp_read(data->handle, buf, count);
  100. stream->eof = (bytes_read <= 0 && bytes_read != LIBSSH2_ERROR_EAGAIN);
  101. return (size_t)(bytes_read<0 ? 0 : bytes_read);
  102. }
  103. /* }}} */
  104. /* {{{ php_ssh2_sftp_stream_close
  105. */
  106. static int php_ssh2_sftp_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
  107. {
  108. php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
  109. libssh2_sftp_close(data->handle);
  110. zend_list_delete(data->sftp_rsrcid);
  111. efree(data);
  112. return 0;
  113. }
  114. /* }}} */
  115. /* {{{ php_ssh2_sftp_stream_seek
  116. */
  117. static int php_ssh2_sftp_stream_seek(php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC)
  118. {
  119. php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
  120. switch (whence) {
  121. case SEEK_END:
  122. {
  123. LIBSSH2_SFTP_ATTRIBUTES attrs;
  124. if (libssh2_sftp_fstat(data->handle, &attrs)) {
  125. return -1;
  126. }
  127. if ((attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) == 0) {
  128. return -1;
  129. }
  130. offset += attrs.filesize;
  131. }
  132. case SEEK_CUR:
  133. {
  134. off_t current_offset = libssh2_sftp_tell(data->handle);
  135. if (current_offset < 0) {
  136. return -1;
  137. }
  138. offset += current_offset;
  139. }
  140. }
  141. libssh2_sftp_seek(data->handle, offset);
  142. if (newoffset) {
  143. *newoffset = offset;
  144. }
  145. return 0;
  146. }
  147. /* }}} */
  148. /* {{{ php_ssh2_sftp_stream_fstat
  149. */
  150. static int php_ssh2_sftp_stream_fstat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
  151. {
  152. php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
  153. LIBSSH2_SFTP_ATTRIBUTES attrs;
  154. if (libssh2_sftp_fstat(data->handle, &attrs)) {
  155. return -1;
  156. }
  157. return php_ssh2_sftp_attr2ssb(ssb, &attrs);
  158. }
  159. /* }}} */
  160. static php_stream_ops php_ssh2_sftp_stream_ops = {
  161. php_ssh2_sftp_stream_write,
  162. php_ssh2_sftp_stream_read,
  163. php_ssh2_sftp_stream_close,
  164. NULL, /* flush */
  165. PHP_SSH2_SFTP_STREAM_NAME,
  166. php_ssh2_sftp_stream_seek,
  167. NULL, /* cast */
  168. php_ssh2_sftp_stream_fstat,
  169. NULL, /* set_option */
  170. };
  171. /* {{{ php_ssh2_sftp_stream_opener
  172. */
  173. static php_stream *php_ssh2_sftp_stream_opener( php_stream_wrapper *wrapper, char *filename, char *mode,
  174. int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
  175. {
  176. php_ssh2_sftp_handle_data *data;
  177. LIBSSH2_SESSION *session = NULL;
  178. LIBSSH2_SFTP *sftp = NULL;
  179. LIBSSH2_SFTP_HANDLE *handle;
  180. php_stream *stream;
  181. int resource_id = 0, sftp_rsrcid = 0;
  182. php_url *resource;
  183. unsigned long flags;
  184. long perms = 0644;
  185. resource = php_ssh2_fopen_wraper_parse_path(filename, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
  186. if (!resource || !session || !sftp) {
  187. return NULL;
  188. }
  189. flags = php_ssh2_parse_fopen_modes(mode);
  190. handle = libssh2_sftp_open(sftp, resource->path, flags, perms);
  191. if (!handle) {
  192. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open %s on remote host", filename);
  193. php_url_free(resource);
  194. zend_list_delete(sftp_rsrcid);
  195. return NULL;
  196. }
  197. data = emalloc(sizeof(php_ssh2_sftp_handle_data));
  198. data->handle = handle;
  199. data->sftp_rsrcid = sftp_rsrcid;
  200. stream = php_stream_alloc(&php_ssh2_sftp_stream_ops, data, 0, mode);
  201. if (!stream) {
  202. libssh2_sftp_close(handle);
  203. zend_list_delete(sftp_rsrcid);
  204. efree(data);
  205. }
  206. php_url_free(resource);
  207. return stream;
  208. }
  209. /* }}} */
  210. /* **********************
  211. * SFTP Directory Ops *
  212. ********************** */
  213. /* {{{ php_ssh2_sftp_dirstream_read
  214. */
  215. static size_t php_ssh2_sftp_dirstream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
  216. {
  217. php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
  218. php_stream_dirent *ent = (php_stream_dirent*)buf;
  219. size_t bytesread = libssh2_sftp_readdir(data->handle, ent->d_name, sizeof(ent->d_name) - 1, NULL);
  220. char *basename = NULL;
  221. size_t basename_len = 0;
  222. if (bytesread <= 0) {
  223. return 0;
  224. }
  225. ent->d_name[bytesread] = 0;
  226. #ifdef ZEND_ENGINE_2
  227. php_basename(ent->d_name, bytesread, NULL, 0, &basename, &basename_len TSRMLS_CC);
  228. #else
  229. /* CURSE YOU BC BREAKS! */
  230. basename = php_basename(ent->d_name, bytesread, NULL, 0);
  231. if (basename) {
  232. basename_len = strlen(basename);
  233. }
  234. #endif
  235. if (!basename) {
  236. return 0;
  237. }
  238. if (!basename_len) {
  239. efree(basename);
  240. return 0;
  241. }
  242. bytesread = MIN(sizeof(ent->d_name) - 1, basename_len);
  243. memcpy(ent->d_name, basename, bytesread);
  244. ent->d_name[bytesread] = 0;
  245. efree(basename);
  246. return sizeof(php_stream_dirent);
  247. }
  248. /* }}} */
  249. /* {{{ php_ssh2_sftp_dirstream_close
  250. */
  251. static int php_ssh2_sftp_dirstream_close(php_stream *stream, int close_handle TSRMLS_DC)
  252. {
  253. php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
  254. libssh2_sftp_close(data->handle);
  255. zend_list_delete(data->sftp_rsrcid);
  256. efree(data);
  257. return 0;
  258. }
  259. /* }}} */
  260. static php_stream_ops php_ssh2_sftp_dirstream_ops = {
  261. NULL, /* write */
  262. php_ssh2_sftp_dirstream_read,
  263. php_ssh2_sftp_dirstream_close,
  264. NULL, /* flush */
  265. PHP_SSH2_SFTP_DIRSTREAM_NAME,
  266. NULL, /* seek */
  267. NULL, /* cast */
  268. NULL, /* fstat */
  269. NULL, /* set_option */
  270. };
  271. /* {{{ php_ssh2_sftp_dirstream_opener
  272. */
  273. static php_stream *php_ssh2_sftp_dirstream_opener( php_stream_wrapper *wrapper, char *filename, char *mode,
  274. int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
  275. {
  276. php_ssh2_sftp_handle_data *data;
  277. LIBSSH2_SESSION *session = NULL;
  278. LIBSSH2_SFTP *sftp = NULL;
  279. LIBSSH2_SFTP_HANDLE *handle;
  280. php_stream *stream;
  281. int resource_id = 0, sftp_rsrcid = 0;
  282. php_url *resource;
  283. resource = php_ssh2_fopen_wraper_parse_path(filename, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
  284. if (!resource || !session || !sftp) {
  285. return NULL;
  286. }
  287. handle = libssh2_sftp_opendir(sftp, resource->path);
  288. if (!handle) {
  289. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open %s on remote host", filename);
  290. php_url_free(resource);
  291. zend_list_delete(sftp_rsrcid);
  292. return NULL;
  293. }
  294. data = emalloc(sizeof(php_ssh2_sftp_handle_data));
  295. data->handle = handle;
  296. data->sftp_rsrcid = sftp_rsrcid;
  297. stream = php_stream_alloc(&php_ssh2_sftp_dirstream_ops, data, 0, mode);
  298. if (!stream) {
  299. libssh2_sftp_close(handle);
  300. zend_list_delete(sftp_rsrcid);
  301. efree(data);
  302. }
  303. php_url_free(resource);
  304. return stream;
  305. }
  306. /* }}} */
  307. /* ****************
  308. * SFTP Wrapper *
  309. **************** */
  310. #ifdef ZEND_ENGINE_2
  311. /* {{{ php_ssh2_sftp_urlstat
  312. */
  313. static int php_ssh2_sftp_urlstat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC)
  314. {
  315. LIBSSH2_SFTP_ATTRIBUTES attrs;
  316. LIBSSH2_SESSION *session = NULL;
  317. LIBSSH2_SFTP *sftp = NULL;
  318. int resource_id = 0, sftp_rsrcid = 0;
  319. php_url *resource;
  320. resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
  321. if (!resource || !session || !sftp || !resource->path) {
  322. return -1;
  323. }
  324. if (libssh2_sftp_stat_ex(sftp, resource->path, strlen(resource->path),
  325. (flags & PHP_STREAM_URL_STAT_LINK) ? LIBSSH2_SFTP_LSTAT : LIBSSH2_SFTP_STAT, &attrs)) {
  326. php_url_free(resource);
  327. zend_list_delete(sftp_rsrcid);
  328. return -1;
  329. }
  330. php_url_free(resource);
  331. /* parse_path addrefs the resource, but we're not holding on to it so we have to delref it before we leave */
  332. zend_list_delete(sftp_rsrcid);
  333. return php_ssh2_sftp_attr2ssb(ssb, &attrs);
  334. }
  335. /* }}} */
  336. /* {{{ php_ssh2_sftp_unlink
  337. */
  338. static int php_ssh2_sftp_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
  339. {
  340. LIBSSH2_SESSION *session = NULL;
  341. LIBSSH2_SFTP *sftp = NULL;
  342. int resource_id = 0, sftp_rsrcid = 0;
  343. php_url *resource;
  344. int result;
  345. resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
  346. if (!resource || !session || !sftp || !resource->path) {
  347. if (resource) {
  348. php_url_free(resource);
  349. }
  350. return 0;
  351. }
  352. result = libssh2_sftp_unlink(sftp, resource->path);
  353. php_url_free(resource);
  354. zend_list_delete(sftp_rsrcid);
  355. /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */
  356. return (result == 0) ? -1 : 0;
  357. }
  358. /* }}} */
  359. /* {{{ php_ssh2_sftp_rename
  360. */
  361. static int php_ssh2_sftp_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC)
  362. {
  363. LIBSSH2_SESSION *session = NULL;
  364. LIBSSH2_SFTP *sftp = NULL;
  365. int resource_id = 0, sftp_rsrcid = 0;
  366. php_url *resource, *resource_to;
  367. int result;
  368. if (strncmp(url_from, "ssh2.sftp://", sizeof("ssh2.sftp://") - 1) ||
  369. strncmp(url_to, "ssh2.sftp://", sizeof("ssh2.sftp://") - 1)) {
  370. return 0;
  371. }
  372. resource_to = php_url_parse(url_to);
  373. if (!resource_to || !resource_to->path) {
  374. if (resource_to) {
  375. php_url_free(resource_to);
  376. }
  377. return 0;
  378. }
  379. resource = php_ssh2_fopen_wraper_parse_path(url_from, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
  380. if (!resource || !session || !sftp || !resource->path) {
  381. if (resource) {
  382. php_url_free(resource);
  383. }
  384. php_url_free(resource_to);
  385. return 0;
  386. }
  387. result = libssh2_sftp_rename(sftp, resource->path, resource_to->path);
  388. php_url_free(resource);
  389. php_url_free(resource_to);
  390. zend_list_delete(sftp_rsrcid);
  391. /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */
  392. return (result == 0) ? -1 : 0;
  393. }
  394. /* }}} */
  395. /* {{{ php_ssh2_sftp_mkdir
  396. */
  397. static int php_ssh2_sftp_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC)
  398. {
  399. LIBSSH2_SESSION *session = NULL;
  400. LIBSSH2_SFTP *sftp = NULL;
  401. int resource_id = 0, sftp_rsrcid = 0;
  402. php_url *resource;
  403. int result;
  404. resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
  405. if (!resource || !session || !sftp || !resource->path) {
  406. if (resource) {
  407. php_url_free(resource);
  408. }
  409. return 0;
  410. }
  411. if (options & PHP_STREAM_MKDIR_RECURSIVE) {
  412. /* Just attempt to make every directory, some will fail, but we only care about the last success/failure */
  413. char *p = resource->path;
  414. while ((p = strchr(p + 1, '/'))) {
  415. libssh2_sftp_mkdir_ex(sftp, resource->path, p - resource->path, mode);
  416. }
  417. }
  418. result = libssh2_sftp_mkdir(sftp, resource->path, mode);
  419. php_url_free(resource);
  420. zend_list_delete(sftp_rsrcid);
  421. /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */
  422. return (result == 0) ? -1 : 0;
  423. }
  424. /* }}} */
  425. /* {{{ php_ssh2_sftp_rmdir
  426. */
  427. static int php_ssh2_sftp_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
  428. {
  429. LIBSSH2_SESSION *session = NULL;
  430. LIBSSH2_SFTP *sftp = NULL;
  431. int resource_id = 0, sftp_rsrcid = 0;
  432. php_url *resource;
  433. int result;
  434. resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
  435. if (!resource || !session || !sftp || !resource->path) {
  436. if (resource) {
  437. php_url_free(resource);
  438. }
  439. return 0;
  440. }
  441. result = libssh2_sftp_rmdir(sftp, resource->path);
  442. php_url_free(resource);
  443. zend_list_delete(sftp_rsrcid);
  444. /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */
  445. return (result == 0) ? -1 : 0;
  446. }
  447. /* }}} */
  448. #endif
  449. static php_stream_wrapper_ops php_ssh2_sftp_wrapper_ops = {
  450. php_ssh2_sftp_stream_opener,
  451. NULL, /* close */
  452. NULL, /* stat */
  453. #ifdef ZEND_ENGINE_2
  454. php_ssh2_sftp_urlstat,
  455. #else
  456. NULL, /* url_stat isn't actually functional prior to PHP5 */
  457. #endif
  458. php_ssh2_sftp_dirstream_opener,
  459. PHP_SSH2_SFTP_WRAPPER_NAME,
  460. #ifdef ZEND_ENGINE_2
  461. php_ssh2_sftp_unlink,
  462. php_ssh2_sftp_rename,
  463. php_ssh2_sftp_mkdir,
  464. php_ssh2_sftp_rmdir,
  465. #endif
  466. };
  467. php_stream_wrapper php_ssh2_sftp_wrapper = {
  468. &php_ssh2_sftp_wrapper_ops,
  469. NULL,
  470. 1,
  471. 0,
  472. NULL,
  473. };
  474. /* *****************
  475. * Userspace API *
  476. ***************** */
  477. /* {{{ proto resource ssh2_sftp(resource session)
  478. * Request the SFTP subsystem from an already connected SSH2 server
  479. */
  480. PHP_FUNCTION(ssh2_sftp)
  481. {
  482. LIBSSH2_SESSION *session;
  483. LIBSSH2_SFTP *sftp;
  484. php_ssh2_sftp_data *data;
  485. zval *zsession;
  486. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zsession) == FAILURE) {
  487. RETURN_FALSE;
  488. }
  489. ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
  490. sftp = libssh2_sftp_init(session);
  491. if (!sftp) {
  492. char *sess_err = "Unknown";
  493. libssh2_session_last_error(session, &sess_err, NULL, 0);
  494. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to startup SFTP subsystem: %s", sess_err);
  495. RETURN_FALSE;
  496. }
  497. data = emalloc(sizeof(php_ssh2_sftp_data));
  498. data->session = session;
  499. data->sftp = sftp;
  500. data->session_rsrcid = Z_LVAL_P(zsession);
  501. zend_list_addref(Z_LVAL_P(zsession));
  502. ZEND_REGISTER_RESOURCE(return_value, data, le_ssh2_sftp);
  503. }
  504. /* }}} */
  505. /* Much of the stuff below can be done via wrapper ops as of PHP5, but is included here for PHP 4.3 users */
  506. /* {{{ proto bool ssh2_sftp_rename(resource sftp, string from, string to)
  507. */
  508. PHP_FUNCTION(ssh2_sftp_rename)
  509. {
  510. php_ssh2_sftp_data *data;
  511. zval *zsftp;
  512. char *src, *dst;
  513. int src_len, dst_len;
  514. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zsftp, &src, &src_len, &dst, &dst_len) == FAILURE) {
  515. RETURN_FALSE;
  516. }
  517. ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
  518. RETURN_BOOL(!libssh2_sftp_rename_ex(data->sftp, src, src_len, dst, dst_len,
  519. LIBSSH2_SFTP_RENAME_OVERWRITE | LIBSSH2_SFTP_RENAME_ATOMIC | LIBSSH2_SFTP_RENAME_NATIVE));
  520. }
  521. /* }}} */
  522. /* {{{ proto bool ssh2_sftp_unlink(resource sftp, string filename)
  523. */
  524. PHP_FUNCTION(ssh2_sftp_unlink)
  525. {
  526. php_ssh2_sftp_data *data;
  527. zval *zsftp;
  528. char *filename;
  529. int filename_len;
  530. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &filename, &filename_len) == FAILURE) {
  531. RETURN_FALSE;
  532. }
  533. ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
  534. RETURN_BOOL(!libssh2_sftp_unlink_ex(data->sftp, filename, filename_len));
  535. }
  536. /* }}} */
  537. /* {{{ proto bool ssh2_sftp_mkdir(resource sftp, string filename[, int mode[, int recursive]])
  538. */
  539. PHP_FUNCTION(ssh2_sftp_mkdir)
  540. {
  541. php_ssh2_sftp_data *data;
  542. zval *zsftp;
  543. char *filename;
  544. int filename_len;
  545. long mode = 0777;
  546. zend_bool recursive = 0;
  547. char *p;
  548. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lb", &zsftp, &filename, &filename_len, &mode, &recursive) == FAILURE) {
  549. RETURN_FALSE;
  550. }
  551. if (filename_len < 1) {
  552. RETURN_FALSE;
  553. }
  554. ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
  555. if (recursive) {
  556. /* Just attempt to make every directory, some will fail, but we only care about the last success/failure */
  557. p = filename;
  558. while ((p = strchr(p + 1, '/'))) {
  559. if ((p - filename) + 1 == filename_len) {
  560. break;
  561. }
  562. libssh2_sftp_mkdir_ex(data->sftp, filename, p - filename, mode);
  563. }
  564. }
  565. RETURN_BOOL(!libssh2_sftp_mkdir_ex(data->sftp, filename, filename_len, mode));
  566. }
  567. /* }}} */
  568. /* {{{ proto bool ssh2_sftp_rmdir(resource sftp, string filename)
  569. */
  570. PHP_FUNCTION(ssh2_sftp_rmdir)
  571. {
  572. php_ssh2_sftp_data *data;
  573. zval *zsftp;
  574. char *filename;
  575. int filename_len;
  576. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &filename, &filename_len) == FAILURE) {
  577. RETURN_FALSE;
  578. }
  579. ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
  580. RETURN_BOOL(!libssh2_sftp_rmdir_ex(data->sftp, filename, filename_len));
  581. }
  582. /* }}} */
  583. /* {{{ php_ssh2_sftp_stat_func
  584. * In PHP4.3 this is the only way to request stat into, in PHP >= 5 you can use the fopen wrapper approach
  585. * Both methods will return identical structures
  586. * (well, the other one will include other values set to 0 but they don't count)
  587. */
  588. static void php_ssh2_sftp_stat_func(INTERNAL_FUNCTION_PARAMETERS, int stat_type)
  589. {
  590. php_ssh2_sftp_data *data;
  591. LIBSSH2_SFTP_ATTRIBUTES attrs;
  592. zval *zsftp;
  593. char *path;
  594. int path_len;
  595. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &path, &path_len) == FAILURE) {
  596. RETURN_FALSE;
  597. }
  598. ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
  599. if (libssh2_sftp_stat_ex(data->sftp, path, path_len, stat_type, &attrs)) {
  600. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to stat remote file");
  601. RETURN_FALSE;
  602. }
  603. array_init(return_value);
  604. if (attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) {
  605. add_index_long(return_value, 7, attrs.filesize);
  606. add_assoc_long(return_value, "size", attrs.filesize);
  607. }
  608. if (attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) {
  609. add_index_long(return_value, 4, attrs.uid);
  610. add_assoc_long(return_value, "uid", attrs.uid);
  611. add_index_long(return_value, 5, attrs.gid);
  612. add_assoc_long(return_value, "gid", attrs.gid);
  613. }
  614. if (attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
  615. add_index_long(return_value, 2, attrs.permissions);
  616. add_assoc_long(return_value, "mode", attrs.permissions);
  617. }
  618. if (attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
  619. add_index_long(return_value, 8, attrs.atime);
  620. add_assoc_long(return_value, "atime", attrs.atime);
  621. add_index_long(return_value, 9, attrs.mtime);
  622. add_assoc_long(return_value, "mtime", attrs.mtime);
  623. }
  624. }
  625. /* }}} */
  626. /* {{{ proto array ssh2_sftp_stat(resource sftp, string path)
  627. */
  628. PHP_FUNCTION(ssh2_sftp_stat)
  629. {
  630. php_ssh2_sftp_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU, LIBSSH2_SFTP_STAT);
  631. }
  632. /* }}} */
  633. /* {{{ proto array ssh2_sftp_lstat(resource sftp, string path)
  634. */
  635. PHP_FUNCTION(ssh2_sftp_lstat)
  636. {
  637. php_ssh2_sftp_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU, LIBSSH2_SFTP_LSTAT);
  638. }
  639. /* }}} */
  640. /* {{{ proto bool ssh2_sftp_symlink(resource sftp, string target, string link)
  641. */
  642. PHP_FUNCTION(ssh2_sftp_symlink)
  643. {
  644. php_ssh2_sftp_data *data;
  645. zval *zsftp;
  646. char *targ, *link;
  647. int targ_len, link_len;
  648. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zsftp, &targ, &targ_len, &link, &link_len) == FAILURE) {
  649. RETURN_FALSE;
  650. }
  651. ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
  652. RETURN_BOOL(!libssh2_sftp_symlink_ex(data->sftp, targ, targ_len, link, link_len, LIBSSH2_SFTP_SYMLINK));
  653. }
  654. /* }}} */
  655. /* {{{ proto string ssh2_sftp_readlink(resource sftp, string link)
  656. */
  657. PHP_FUNCTION(ssh2_sftp_readlink)
  658. {
  659. php_ssh2_sftp_data *data;
  660. zval *zsftp;
  661. char *link;
  662. int targ_len = 0, link_len;
  663. char targ[8192];
  664. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &link, &link_len) == FAILURE) {
  665. RETURN_FALSE;
  666. }
  667. ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
  668. if ((targ_len = libssh2_sftp_symlink_ex(data->sftp, link, link_len, targ, 8192, LIBSSH2_SFTP_READLINK)) < 0) {
  669. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to read link '%s'", link);
  670. RETURN_FALSE;
  671. }
  672. RETURN_STRINGL(targ, targ_len, 1);
  673. }
  674. /* }}} */
  675. /* {{{ proto string ssh2_sftp_realpath(resource sftp, string filename)
  676. */
  677. PHP_FUNCTION(ssh2_sftp_realpath)
  678. {
  679. php_ssh2_sftp_data *data;
  680. zval *zsftp;
  681. char *link;
  682. int targ_len = 0, link_len;
  683. char targ[8192];
  684. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &link, &link_len) == FAILURE) {
  685. RETURN_FALSE;
  686. }
  687. ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
  688. if ((targ_len = libssh2_sftp_symlink_ex(data->sftp, link, link_len, targ, 8192, LIBSSH2_SFTP_REALPATH)) < 0) {
  689. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to resolve realpath for '%s'", link);
  690. RETURN_FALSE;
  691. }
  692. RETURN_STRINGL(targ, targ_len, 1);
  693. }
  694. /* }}} */
  695. /*
  696. * Local variables:
  697. * tab-width: 4
  698. * c-basic-offset: 4
  699. * indent-tabs-mode: t
  700. * End:
  701. */