Skip to content

First fixes for a 64bit compatible ftp extension #214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 18 additions & 36 deletions ext/ftp/ftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -610,16 +610,16 @@ ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filenam
/* {{{ ftp_alloc
*/
int
ftp_alloc(ftpbuf_t *ftp, const int size, char **response)
ftp_alloc(ftpbuf_t *ftp, const long size, char **response)
{
char buffer[64];

if (ftp == NULL || size <= 0) {
return 0;
}

snprintf(buffer, sizeof(buffer) - 1, "%d", size);

snprintf(buffer, sizeof(buffer) - 1, "%ld", size);
if (!ftp_putcmd(ftp, "ALLO", buffer)) {
return 0;
}
Expand Down Expand Up @@ -785,7 +785,7 @@ ftp_pasv(ftpbuf_t *ftp, int pasv)
/* {{{ ftp_get
*/
int
ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, int resumepos TSRMLS_DC)
ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, long resumepos TSRMLS_DC)
{
databuf_t *data = NULL;
int lastch;
Expand All @@ -806,11 +806,7 @@ ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type,
ftp->data = data;

if (resumepos > 0) {
if (resumepos > 2147483647) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP cannot handle files greater than 2147483647 bytes.");
goto bail;
}
snprintf(arg, sizeof(arg), "%u", resumepos);
snprintf(arg, sizeof(arg), "%ld", resumepos);
if (!ftp_putcmd(ftp, "REST", arg)) {
goto bail;
}
Expand Down Expand Up @@ -883,10 +879,10 @@ ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type,
/* {{{ ftp_put
*/
int
ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos TSRMLS_DC)
ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, long startpos TSRMLS_DC)
{
databuf_t *data = NULL;
int size;
long size;
char *ptr;
int ch;
char arg[11];
Expand All @@ -903,11 +899,7 @@ ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, i
ftp->data = data;

if (startpos > 0) {
if (startpos > 2147483647) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP cannot handle files with a size greater than 2147483647 bytes.");
goto bail;
}
snprintf(arg, sizeof(arg), "%u", startpos);
snprintf(arg, sizeof(arg), "%ld", startpos);
if (!ftp_putcmd(ftp, "REST", arg)) {
goto bail;
}
Expand Down Expand Up @@ -964,7 +956,7 @@ ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, i

/* {{{ ftp_size
*/
int
long
ftp_size(ftpbuf_t *ftp, const char *path)
{
if (ftp == NULL) {
Expand All @@ -979,7 +971,7 @@ ftp_size(ftpbuf_t *ftp, const char *path)
if (!ftp_getresp(ftp) || ftp->resp != 213) {
return -1;
}
return atoi(ftp->inbuf);
return atol(ftp->inbuf);
}
/* }}} */

Expand Down Expand Up @@ -1141,7 +1133,7 @@ ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const char *args)
int
ftp_readline(ftpbuf_t *ftp)
{
int size, rcvd;
long size, rcvd;
char *data, *eol;

/* shift the extra to the front */
Expand Down Expand Up @@ -1234,7 +1226,8 @@ ftp_getresp(ftpbuf_t *ftp)
int
my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len)
{
int n, size, sent;
long size, sent;
int n;

size = len;
while (size) {
Expand Down Expand Up @@ -1704,7 +1697,7 @@ ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path TSRMLS_DC)
/* {{{ ftp_nb_get
*/
int
ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, int resumepos TSRMLS_DC)
ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, long resumepos TSRMLS_DC)
{
databuf_t *data = NULL;
char arg[11];
Expand All @@ -1722,14 +1715,7 @@ ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t typ
}

if (resumepos>0) {
/* We are working on an architecture that supports 64-bit integers
* since php is 32 bit by design, we bail out with warning
*/
if (resumepos > 2147483647) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP cannot handle files greater than 2147483648 bytes.");
goto bail;
}
snprintf(arg, sizeof(arg), "%u", resumepos);
snprintf(arg, sizeof(arg), "%ld", resumepos);
if (!ftp_putcmd(ftp, "REST", arg)) {
goto bail;
}
Expand Down Expand Up @@ -1828,7 +1814,7 @@ ftp_nb_continue_read(ftpbuf_t *ftp TSRMLS_DC)
/* {{{ ftp_nb_put
*/
int
ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos TSRMLS_DC)
ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, long startpos TSRMLS_DC)
{
databuf_t *data = NULL;
char arg[11];
Expand All @@ -1843,11 +1829,7 @@ ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type
goto bail;
}
if (startpos > 0) {
if (startpos > 2147483647) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP cannot handle files with a size greater than 2147483647 bytes.");
goto bail;
}
snprintf(arg, sizeof(arg), "%u", startpos);
snprintf(arg, sizeof(arg), "%ld", startpos);
if (!ftp_putcmd(ftp, "REST", arg)) {
goto bail;
}
Expand Down Expand Up @@ -1884,7 +1866,7 @@ ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type
int
ftp_nb_continue_write(ftpbuf_t *ftp TSRMLS_DC)
{
int size;
long size;
char *ptr;
int ch;

Expand Down
12 changes: 6 additions & 6 deletions ext/ftp/ftp.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ int ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int fi
* however some servers will not accept STOR or APPE until ALLO is confirmed.
* If response is passed, it is estrdup()ed from ftp->inbuf and must be freed
* or assigned to a zval returned to the user */
int ftp_alloc(ftpbuf_t *ftp, const int size, char **response);
int ftp_alloc(ftpbuf_t *ftp, const long size, char **response);

/* returns a NULL-terminated array of filenames in the given path
* or NULL on error. the return array must be freed (but don't
Expand All @@ -169,15 +169,15 @@ int ftp_pasv(ftpbuf_t *ftp, int pasv);
/* retrieves a file and saves its contents to outfp
* returns true on success, false on error
*/
int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, int resumepos TSRMLS_DC);
int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, long resumepos TSRMLS_DC);

/* stores the data from a file, socket, or process as a file on the remote server
* returns true on success, false on error
*/
int ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos TSRMLS_DC);
int ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, long startpos TSRMLS_DC);

/* returns the size of the given file, or -1 on error */
int ftp_size(ftpbuf_t *ftp, const char *path);
long ftp_size(ftpbuf_t *ftp, const char *path);

/* returns the last modified time of the given file, or -1 on error */
time_t ftp_mdtm(ftpbuf_t *ftp, const char *path);
Expand All @@ -194,12 +194,12 @@ int ftp_site(ftpbuf_t *ftp, const char *cmd);
/* retrieves part of a file and saves its contents to outfp
* returns true on success, false on error
*/
int ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, int resumepos TSRMLS_DC);
int ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, long resumepos TSRMLS_DC);

/* stores the data from a file, socket, or process as a file on the remote server
* returns true on success, false on error
*/
int ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos TSRMLS_DC);
int ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, long startpos TSRMLS_DC);

/* continues a previous nb_(f)get command
*/
Expand Down
16 changes: 7 additions & 9 deletions ext/ftp/php_ftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -784,8 +784,8 @@ PHP_FUNCTION(ftp_nb_fget)
ftptype_t xtype;
php_stream *stream;
char *file;
int file_len, ret;
long mode, resumepos=0;
int file_len;
long mode, resumepos=0, ret;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrsl|l", &z_ftp, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) {
return;
Expand Down Expand Up @@ -968,9 +968,7 @@ PHP_FUNCTION(ftp_nb_get)
RETURN_LONG(PHP_FTP_FAILED);
}

if (ret == PHP_FTP_FINISHED) {
php_stream_close(outstream);
}
php_stream_close(outstream);

RETURN_LONG(ret);
}
Expand All @@ -982,7 +980,7 @@ PHP_FUNCTION(ftp_nb_continue)
{
zval *z_ftp;
ftpbuf_t *ftp;
int ret;
long ret;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) {
return;
Expand Down Expand Up @@ -1120,7 +1118,7 @@ PHP_FUNCTION(ftp_put)
ftpbuf_t *ftp;
ftptype_t xtype;
char *remote, *local;
int remote_len, local_len;
long remote_len, local_len;
long mode, startpos=0;
php_stream *instream;

Expand Down Expand Up @@ -1173,8 +1171,8 @@ PHP_FUNCTION(ftp_nb_put)
ftpbuf_t *ftp;
ftptype_t xtype;
char *remote, *local;
int remote_len, local_len, ret;
long mode, startpos=0;
int remote_len, local_len;
long mode, startpos=0, ret;
php_stream *instream;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rppl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
Expand Down
20 changes: 20 additions & 0 deletions ext/ftp/tests/filesize_large.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
Verify php can handle filesizes >32bit
--SKIPIF--
<?php
require 'skipif.inc';
?>
--FILE--
<?php
require 'server.inc';

$ftp = ftp_connect('127.0.0.1', $port);
if (!$ftp) die("Couldn't connect to the server");

ftp_login($ftp, 'user', 'pass');
var_dump(ftp_size($ftp, 'largefile'));

ftp_close($ftp);
?>
--EXPECT--
int(5368709120)
36 changes: 36 additions & 0 deletions ext/ftp/tests/ftp_nb_get_large.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
--TEST--
Testing ftp_nb_fget can handle large files incl. resume
--SKIPIF--
<?php
require 'skipif.inc';
if (2147483647 == PHP_INT_MAX) {
die('not supported on this system');
}
if (disk_free_space(__DIR__) < 10*1024*1024*1024) {
die('not enough disk space');
}
?>
--FILE--
<?php
require 'server.inc';

$ftp = ftp_connect('127.0.0.1', $port);
ftp_login($ftp, 'user', 'pass');
if (!$ftp) die("Couldn't connect to the server");

$local_file = dirname(__FILE__) . DIRECTORY_SEPARATOR . "localfile.txt";
touch($local_file);
ftp_nb_get($ftp, $local_file, 'fget_large.txt', FTP_BINARY, 5368709119);
$fp = fopen($local_file, 'r');
fseek($fp, 5368709119);
var_dump(fread($fp, 1));
var_dump(filesize($local_file));
fclose($fp);
?>
--CLEAN--
<?php
@unlink(dirname(__FILE__) . DIRECTORY_SEPARATOR . "localfile.txt");
?>
--EXPECT--
string(1) "X"
int(5368709120)
23 changes: 17 additions & 6 deletions ext/ftp/tests/server.inc
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,17 @@ if ($pid) {
$transfer_type = $ascii? 'ASCII' : 'BINARY' ;
fputs($fs, "Bar\r\n");
fputs($s, "226 Closing data Connection.\r\n");
break;
break;
case "fget_large":
fputs($s, "150 File status okay; about to open data connection.\r\n");
$transfer_type = $ascii? 'ASCII' : 'BINARY' ;
if ($GLOBALS['rest_pos'] == '5368709119') {
fputs($fs, "X");
} else {
fputs($fs, "Y");
}
fputs($s, "226 Closing data Connection.\r\n");
break;
default:
fputs($s, "550 {$matches[1]}: No such file or directory \r\n");
break;
Expand Down Expand Up @@ -393,11 +403,12 @@ if ($pid) {
}elseif (preg_match('/^LIST no_exists\//', $buf, $matches)) {
fputs($s, "425 Error establishing connection\r\n");

}elseif (preg_match('/^REST \d+/', $buf, $matches)) {
}elseif (preg_match('/^REST (\d+)/', $buf, $matches)) {
$GLOBALS['rest_pos'] = $matches[1];
fputs($s, "350 OK\r\n");
}

else {
}elseif (preg_match('/^SIZE largefile/', $buf)) {
fputs($s, "213 5368709120\r\n");
}else {
fputs($s, "500 Syntax error, command unrecognized.\r\n");
dump_and_exit($buf);
}
Expand All @@ -407,4 +418,4 @@ if ($pid) {
}

fclose($socket);
?>
?>