Removed system headers from uftps.h.
[uftps.git] / misc.c
blob0577dedfb65c89d2f9ebecc7ddb6d2d69d66d4e0
1 /*
2 * User FTP Server, Share folders over FTP without being root.
3 * Copyright (C) 2008 Isaac Jurado
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option) any later
8 * version.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * details.
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 * Miscellaneous helper functions.
24 #include "uftps.h"
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdio.h>
33 * fatal
35 * Show 'msg' followed by the system error and exit badly.
37 void fatal (char *msg)
39 fputs("FATAL ERROR: ", stderr);
40 perror(msg);
41 exit(EXIT_FAILURE);
46 * send_reply
48 * Send 'msg' through socket 'sk'. Because a single send() call doesn't ensure
49 * that all data is transferred (or maybe the call is interrupted), we need to
50 * place it in a small loop to wait until all 'msg' contents, at least, gets
51 * copied onto the internal TCP/IP stack buffers.
53 void send_reply (int sk, char *msg)
55 int msglen, b;
57 debug_msg("<<< %s", msg);
59 msglen = strlen(msg);
60 do {
61 b = send(sk, msg, msglen, 0);
62 if (b == -1)
63 fatal("Could not send reply");
64 msg += b;
65 msglen -= b;
66 } while (msglen > 0);
71 #if 0
73 * str_to_ll
75 * Converts a string to its numeric value in 64 bit representation. Quote from
76 * sysutil.c file of VsFTPd:
78 * ``atoll() is C99 standard - but even modern FreeBSD, OpenBSD don't
79 * haveit, so we'll supply our own''
81 * This function is almost a literal copy of vsf_sysutil_a_to_filesize_t(),
82 * present in that file. The only difference is that the string is processed
83 * from left to right, in contrast with the original. Therefore, here, negative
84 * numbers are directly converted to 0.
86 long long str_to_ll (char *str)
88 long long value = 0;
90 if (strlen(str) <= 15) {
91 while (*str) {
92 if (*str < '0' || *str > '9')
93 break;
94 value *= 10;
95 value += *str - '0';
96 str++;
99 if (value < 0)
100 value = 0;
101 return value;
103 #endif
107 * path_is_secure
109 * Check if 'path' is trying to access beyond the Basedir. We shouldn't allow
110 * that because we try to emulate chroot().
112 * This implementation is basically a small DFA (Deterministic Finite Automata)
113 * which parses the path looking for any of the substrings "./" or "../" at the
114 * beginning, "/./" or "/../" within, or else "/." or "/.." at the end.
116 int path_is_secure (char *path)
119 * Current state ____ ____ Input value
120 * \ / */
121 const static int next_state[5][3] = {
122 /* State 0 */ { 0, 1, 4 }, /* Input values: */
123 /* State 1 */ { 3, 2, 4 }, /* */
124 /* State 2 */ { 3, 4, 4 }, /* '/' = 0 */
125 /* State 3 */ { 3, 3, 3 }, /* '.' = 1 */
126 /* State 4 */ { 0, 4, 4 } /* other = 2 */
128 int state = 0; /* Initial state */
129 int input;
131 while (*path != '\0') {
132 switch (*path) {
133 case '/': input = 0; break;
134 case '.': input = 1; break;
135 default : input = 2;
137 state = next_state[state][input];
138 path++;
141 /* Accepting states (safe path) are: */
142 return state == 0 || state == 4;
146 #ifdef DEBUG
148 * debug_msg
150 * Only implemented when debug flags are enabled. Display an information
151 * message to the stderr. Useful to follow the progress of the command-reply
152 * exchange without the need of a debugger.
154 void debug_msg (const char *format, ...)
156 va_list params;
158 fprintf(stderr, "(%d) ", getpid());
159 va_start(params, format);
160 vfprintf(stderr, format, params);
161 va_end(params);
163 #endif