Coding style fix.
[uftps.git] / misc.c
blob75b1ef197be2a78dafa2c444b90326b530d05b55
1 /*
2 * User FTP Server
3 * Author : C2H5OH
4 * License: GPL v2
6 * misc.c - Miscellaneous helper functions.
7 */
9 #include "uftps.h"
12 * fatal
14 * Show 'msg' followed by the system error and exit badly.
16 void fatal (char *msg)
18 fputs("FATAL ERROR: ", stderr);
19 perror(msg);
20 exit(EXIT_FAILURE);
25 * send_reply
27 * Send 'msg' through socket 'sk'. Because a single send() call doesn't ensure
28 * that all data is transferred (or maybe the call is interrupted), we need to
29 * place it in a small loop to wait until all 'msg' contents, at least, gets
30 * copied onto the internal TCP/IP stack buffers.
32 void send_reply (int sk, char *msg)
34 int msglen, b;
36 debug_msg("<<< %s", msg);
38 msglen = strlen(msg);
39 do {
40 b = send(sk, msg, msglen, 0);
41 if (b == -1)
42 fatal("Could not send reply");
43 msg += b;
44 msglen -= b;
45 } while (msglen > 0);
50 #if 0
52 * str_to_ll
54 * Converts a string to its numeric value in 64 bit representation. Quote from
55 * sysutil.c file of VsFTPd:
57 * ``atoll() is C99 standard - but even modern FreeBSD, OpenBSD don't
58 * haveit, so we'll supply our own''
60 * This function is almost a literal copy of vsf_sysutil_a_to_filesize_t(),
61 * present in that file. The only difference is that the string is processed
62 * from left to right, in contrast with the original. Therefore, here, negative
63 * numbers are directly converted to 0.
65 long long str_to_ll (char *str)
67 long long value = 0;
69 if (strlen(str) <= 15) {
70 while (*str) {
71 if (*str < '0' || *str > '9')
72 break;
73 value *= 10;
74 value += *str - '0';
75 str++;
78 if (value < 0)
79 value = 0;
80 return value;
82 #endif
86 * path_is_secure
88 * Check if 'path' is trying to access beyond the Basedir. We shouldn't allow
89 * that because we try to emulate chroot().
91 * This implementation is basically a small DFA (Deterministic Finite Automata)
92 * which parses the path looking for any of the substrings "./" or "../" at the
93 * beginning, "/./" or "/../" within, or else "/." or "/.." at the end.
95 int path_is_secure (char *path)
98 * Current state ____ ____ Input value
99 * \ / */
100 const static int next_state[5][3] = {
101 /* State 0 */ { 0, 1, 4 }, /* Input values: */
102 /* State 1 */ { 3, 2, 4 }, /* */
103 /* State 2 */ { 3, 4, 4 }, /* '/' = 0 */
104 /* State 3 */ { 3, 3, 3 }, /* '.' = 1 */
105 /* State 4 */ { 0, 4, 4 } /* other = 2 */
107 int state = 0; /* Initial state */
108 int input;
110 while (*path != '\0') {
111 switch (*path) {
112 case '/': input = 0; break;
113 case '.': input = 1; break;
114 default : input = 2;
116 state = next_state[state][input];
117 path++;
120 /* Accepting states (safe path) are: */
121 return state == 0 || state == 4;
125 #ifdef DEBUG
127 * debug_msg
129 * Only implemented when debug flags are enabled. Display an information message
130 * to the stderr. Useful to follow the progress of the command-reply exchange
131 * without the need of a debugger.
133 void debug_msg (const char *format, ...)
135 va_list params;
137 fprintf(stderr, "(%d) ", getpid());
138 va_start(params, format);
139 vfprintf(stderr, format, params);
140 va_end(params);
142 #endif