|
1 | | -/* $OpenBSD: ftpd.c,v 1.3 1996/07/27 07:26:39 joshd Exp $ */ |
| 1 | +/* $OpenBSD: ftpd.c,v 1.4 1996/07/28 19:45:36 downsj Exp $ */ |
2 | 2 | /* $NetBSD: ftpd.c,v 1.15 1995/06/03 22:46:47 mycroft Exp $ */ |
3 | 3 |
|
4 | 4 | /* |
@@ -56,6 +56,7 @@ static char rcsid[] = "$NetBSD: ftpd.c,v 1.15 1995/06/03 22:46:47 mycroft Exp $" |
56 | 56 | #include <sys/ioctl.h> |
57 | 57 | #include <sys/socket.h> |
58 | 58 | #include <sys/wait.h> |
| 59 | +#include <sys/mman.h> |
59 | 60 |
|
60 | 61 | #include <netinet/in.h> |
61 | 62 | #include <netinet/in_systm.h> |
@@ -187,7 +188,7 @@ static FILE *getdatasock __P((char *)); |
187 | 188 | static char *gunique __P((char *)); |
188 | 189 | static void lostconn __P((int)); |
189 | 190 | static int receive_data __P((FILE *, FILE *)); |
190 | | -static void send_data __P((FILE *, FILE *, off_t)); |
| 191 | +static void send_data __P((FILE *, FILE *, off_t, off_t, int)); |
191 | 192 | static struct passwd * |
192 | 193 | sgetpwnam __P((char *)); |
193 | 194 | static char *sgetsave __P((char *)); |
@@ -750,7 +751,8 @@ retrieve(cmd, name) |
750 | 751 | dout = dataconn(name, st.st_size, "w"); |
751 | 752 | if (dout == NULL) |
752 | 753 | goto done; |
753 | | - send_data(fin, dout, st.st_blksize); |
| 754 | + send_data(fin, dout, st.st_blksize, st.st_size, |
| 755 | + (restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode))); |
754 | 756 | (void) fclose(dout); |
755 | 757 | data = -1; |
756 | 758 | pdata = -1; |
@@ -980,17 +982,20 @@ dataconn(name, size, mode) |
980 | 982 |
|
981 | 983 | /* |
982 | 984 | * Tranfer the contents of "instr" to "outstr" peer using the appropriate |
983 | | - * encapsulation of the data subject * to Mode, Structure, and Type. |
| 985 | + * encapsulation of the data subject to Mode, Structure, and Type. |
984 | 986 | * |
985 | 987 | * NB: Form isn't handled. |
986 | 988 | */ |
987 | 989 | static void |
988 | | -send_data(instr, outstr, blksize) |
| 990 | +send_data(instr, outstr, blksize, filesize, isreg) |
989 | 991 | FILE *instr, *outstr; |
990 | 992 | off_t blksize; |
| 993 | + off_t filesize; |
| 994 | + int isreg; |
991 | 995 | { |
992 | 996 | int c, cnt, filefd, netfd; |
993 | | - char *buf; |
| 997 | + char *buf, *bp; |
| 998 | + size_t len; |
994 | 999 |
|
995 | 1000 | transflag++; |
996 | 1001 | if (setjmp(urgcatch)) { |
@@ -1020,13 +1025,45 @@ send_data(instr, outstr, blksize) |
1020 | 1025 |
|
1021 | 1026 | case TYPE_I: |
1022 | 1027 | case TYPE_L: |
| 1028 | + /* |
| 1029 | + * isreg is only set if we are not doing restart and we |
| 1030 | + * are sending a regular file |
| 1031 | + */ |
| 1032 | + netfd = fileno(outstr); |
| 1033 | + filefd = fileno(instr); |
| 1034 | + |
| 1035 | + if (isreg && filesize < (off_t)16 * 1024 * 1024) { |
| 1036 | + buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd, |
| 1037 | + (off_t)0); |
| 1038 | + if (!buf) { |
| 1039 | + syslog(LOG_WARNING, "mmap(%lu): %m", |
| 1040 | + (unsigned long)filesize); |
| 1041 | + goto oldway; |
| 1042 | + } |
| 1043 | + bp = buf; |
| 1044 | + len = filesize; |
| 1045 | + do { |
| 1046 | + cnt = write(netfd, bp, len); |
| 1047 | + len -= cnt; |
| 1048 | + bp += cnt; |
| 1049 | + if (cnt > 0) byte_count += cnt; |
| 1050 | + } while(cnt > 0 && len > 0); |
| 1051 | + |
| 1052 | + transflag = 0; |
| 1053 | + munmap(buf, (size_t)filesize); |
| 1054 | + if (cnt < 0) |
| 1055 | + goto data_err; |
| 1056 | + reply(226, "Transfer complete."); |
| 1057 | + return; |
| 1058 | + } |
| 1059 | + |
| 1060 | +oldway: |
1023 | 1061 | if ((buf = malloc((u_int)blksize)) == NULL) { |
1024 | 1062 | transflag = 0; |
1025 | 1063 | perror_reply(451, "Local resource failure: malloc"); |
1026 | 1064 | return; |
1027 | 1065 | } |
1028 | | - netfd = fileno(outstr); |
1029 | | - filefd = fileno(instr); |
| 1066 | + |
1030 | 1067 | while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && |
1031 | 1068 | write(netfd, buf, cnt) == cnt) |
1032 | 1069 | byte_count += cnt; |
|
0 commit comments