1 /* retr.c - twoftpd routines for retrieving files
2  * Copyright (C) 2008  Bruce Guenter <bruce@untroubled.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 #include <fcntl.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include "twoftpd.h"
22 #include "backend.h"
23 
24 unsigned long startpos = 0;
25 
handle_rest(void)26 int handle_rest(void)
27 {
28   const char* end;
29   startpos = strtou(req_param, &end);
30   if (*end != 0) {
31     startpos = 0;
32     return respond(501, 1, "Invalid number given for REST.");
33   }
34   return respond(350, 1, "Start position for transfer has been set.");
35 }
36 
xlate_ascii(char * out,const char * in,unsigned long inlen)37 static unsigned long xlate_ascii(char* out,
38 				 const char* in,
39 				 unsigned long inlen)
40 {
41   unsigned long outlen;
42   for (outlen = 0; inlen > 0; --inlen, ++in) {
43     if (*in == LF) {
44       *out++ = CR;
45       ++outlen;
46     }
47     *out++ = *in;
48     ++outlen;
49   }
50   return outlen;
51 }
52 
handle_retr(void)53 int handle_retr(void)
54 {
55   int in;
56   int out;
57   unsigned long ss;
58   struct stat st;
59   unsigned long bytes_in;
60   unsigned long bytes_out;
61   int result;
62 
63   ss = startpos;
64   startpos = 0;
65   if ((in = open_fd(req_param, O_RDONLY, 0)) == -1)
66     return respond_syserr(550, "Could not open input file");
67   if (fstat(in, &st) != 0) {
68     close(in);
69     return respond_syserr(550, "Could not fstat input file");
70   }
71   if (!S_ISREG(st.st_mode)) {
72     close(in);
73     return respond(550, 1, "Requested name is not a regular file");
74   }
75   if (ss && !lseek(in, ss, SEEK_SET)) {
76     close(in);
77     return respond(550, 1, "Could not seek to start position in input file.");
78   }
79   if ((out = make_out_connection()) == -1) {
80     close(in);
81     return 1;
82   }
83   result = copy_xlate_close(in, out, timeout * 1000,
84 			    binary_flag ? 0 : xlate_ascii,
85 			    &bytes_in, &bytes_out);
86   return respond_xferresult(result, bytes_out, 1);
87 }
88