mirror of
https://github.com/ps5-payload-dev/ftpsrv.git
synced 2026-10-19 02:10:54 -05:00
RETR: use sendfile() to transmit files for improved performance and reduced memory footprint
This commit is contained in:
1 parent
d4d0aede3e
commit
c3afb40d36
7 files changed
+125
-8
No files matched your search
@@ -21,6 +21,7 @@ VERSION_TAG := $(shell git describe --abbrev=6 --dirty --always --tags)
|
||||
CFLAGS := -Wall -Werror -DVERSION_TAG=\"$(VERSION_TAG)\" -I.
|
||||
SOURCE := srv.c cmd.c notify.c io.c self.c sha256.c
|
||||
SOURCE += posix/main.c posix/cmd.c posix/self.c
|
||||
SOURCE += io-linux.c
|
||||
|
||||
all: $(ELF)
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ VERSION_TAG := $(shell git describe --abbrev=6 --dirty --always --tags)
|
||||
CFLAGS := -Wall -Werror -DVERSION_TAG=\"$(VERSION_TAG)\" -I.
|
||||
SOURCE := srv.c cmd.c notify.c io.c self.c sha256.c
|
||||
SOURCE += orbis/main.c orbis/cmd.c orbis/self.c
|
||||
SOURCE += io-freebsd.c
|
||||
|
||||
all: $(ELF)
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ VERSION_TAG := $(shell git describe --abbrev=6 --dirty --always --tags)
|
||||
CFLAGS := -Wall -Werror -DVERSION_TAG=\"$(VERSION_TAG)\" -I.
|
||||
SOURCE := srv.c cmd.c notify.c io.c self.c sha256.c
|
||||
SOURCE += prospero/main.c prospero/cmd.c prospero/self.c
|
||||
SOURCE += io-freebsd.c
|
||||
|
||||
all: $(ELF)
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ along with this program; see the file COPYING. If not, see
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@@ -518,9 +519,6 @@ ftp_cmd_RETR_fd(ftp_env_t *env, int fd) {
|
||||
if(fstat(fd, &st)) {
|
||||
return ftp_perror(env);
|
||||
}
|
||||
if(lseek(fd, off, SEEK_SET) < 0) {
|
||||
return ftp_perror(env);
|
||||
}
|
||||
|
||||
if(ftp_active_printf(env, "150 Starting data transfer\r\n")) {
|
||||
return -1;
|
||||
@@ -530,16 +528,18 @@ ftp_cmd_RETR_fd(ftp_env_t *env, int fd) {
|
||||
return ftp_perror(env);
|
||||
}
|
||||
|
||||
if(io_ncopy(fd, env->data_fd, st.st_size - off)) {
|
||||
err = ftp_perror(env);
|
||||
ftp_data_close(env);
|
||||
return err;
|
||||
}
|
||||
err = io_sendfile(fd, env->data_fd, off, st.st_size - off);
|
||||
|
||||
if(ftp_data_close(env)) {
|
||||
return ftp_perror(env);
|
||||
}
|
||||
|
||||
if(err) {
|
||||
return ftp_perror(env);
|
||||
}
|
||||
|
||||
env->data_offset = 0;
|
||||
|
||||
return ftp_active_printf(env, "226 Transfer completed\r\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/* Copyright (C) 2026 John Törnblom
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include "io.h"
|
||||
|
||||
|
||||
int
|
||||
io_sendfile(int fd, int s, off_t offset, size_t n) {
|
||||
off_t copied = 0;
|
||||
off_t sbytes = 0;
|
||||
size_t nbytes;
|
||||
|
||||
while (copied < n) {
|
||||
nbytes = n - copied;
|
||||
if(nbytes > IO_COPY_BUFSIZE) {
|
||||
nbytes = IO_COPY_BUFSIZE;
|
||||
}
|
||||
|
||||
if(sendfile(fd, s, offset, nbytes, 0, &sbytes, 0) < 0) {
|
||||
if(errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(sbytes == 0) {
|
||||
errno = EPIPE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
copied += sbytes;
|
||||
offset += sbytes;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/* Copyright (C) 2026 John Törnblom
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include "io.h"
|
||||
|
||||
|
||||
int
|
||||
io_sendfile(int in_fd, int out_fd, off_t offset, size_t n) {
|
||||
off_t copied = 0;
|
||||
size_t count;
|
||||
ssize_t r;
|
||||
|
||||
while (copied < n) {
|
||||
count = n - copied;
|
||||
if(count > IO_COPY_BUFSIZE) {
|
||||
count = IO_COPY_BUFSIZE;
|
||||
}
|
||||
|
||||
if((r=sendfile(out_fd, in_fd, &offset, count)) < 0) {
|
||||
if(errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if(r == 0) {
|
||||
errno = EPIPE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
copied += r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,12 @@ int io_nwrite(int fd, const void* buf, size_t n);
|
||||
int io_ncopy(int fd_in, int fd_out, size_t n);
|
||||
|
||||
|
||||
/**
|
||||
* Copy exactly N bytes from a file descriptor to a socket.
|
||||
**/
|
||||
int io_sendfile(int fd, int sock, off_t off, size_t n);
|
||||
|
||||
|
||||
/**
|
||||
* Read exactly N bytes from the given file descriptor without affecting its
|
||||
* position.
|
||||
|
||||
Reference in new issue
Block a user