Added a specific reply function for the data channel.
[uftps.git] / expand_arg.c
blob6522589e27b69039b9330ee0bf9d74b25ae0a3c9
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
20 #include "uftps.h"
21 #include <string.h>
25 * Apply new path components to an existing working directory. The working
26 * directory is contained (full path) in "wd", which is a buffer with a capacity
27 * of LINE_SIZE bytes. Parameter "len" specifies the current length of the
28 * working directory.
30 * This function returns the length of "wd" after applying "path" on it, which
31 * means that the working directory is modified in-place. In case the working
32 * directory would exceed LINE_SIZE bytes (at any stage), -1 is returned.
34 * NOTE: Path lengths always include the terminating null byte. This means that
35 * the last useful character of the path is at length - 2.
37 static int apply_path (const char *path, char *wd, int len)
39 int i;
41 if (*path == '/')
43 /* Absolute path, truncate wd */
44 wd[0] = '.';
45 wd[1] = '/';
46 wd[2] = '\0';
47 len = 3;
50 do {
51 /* Combine delimiters */
52 while (*path == '/')
53 path++;
55 if (*path == '\0')
56 /* No more components to apply */
57 break;
59 /* Isolate next component */
60 i = 0;
61 while (path[i] != '/' && path[i] != '\0')
62 i++;
64 if (i == 2 && path[0] == '.' && path[1] == '.')
66 /* Return to parent directory, found ".." */
67 while (wd[len] != '/')
68 len--;
69 if (len == 1)
70 len++; /* Root reached, fix */
71 wd[len] = '\0';
72 len++;
74 else if (i != 1 || path[0] != '.')
76 /* Bounds check */
77 if (len + i >= LINE_SIZE)
78 return -1;
80 /* Apply component, because it is different than "." */
81 if (len > 3)
82 wd[len - 1] = '/';
83 else
84 len--; /* Skip delimiter at root */
86 memcpy(wd + len, path, i);
87 len += i + 1;
88 wd[len - 1] = '\0';
91 /* Now skip to the next component */
92 path += i;
93 } while (1);
95 return len;
100 * Expand the command argument to its corresponding full path. This is
101 * necessary because chdir() is never performed so the correct path needs to be
102 * resolved for each file or directory to be accessed.
104 * Returns the length of the expanded argument, including the trailing null
105 * byte (just as apply_path() does). Also note that the expanded argument is
106 * saved in the auxiliary buffer and the argument pointer is redirected
107 * accordingly.
109 int expand_arg (void)
111 int len = SS.cwd_len;
113 /* Even if the argument is empty, list_dir() requires the current
114 * working directory to be copied */
115 memcpy(SS.aux, SS.cwd, len);
117 if (SS.arg != NULL)
119 len = apply_path(SS.arg, SS.aux, len);
120 if (len == -1)
122 reply_c("552 Path overflow.\r\n");
123 fatal("Path overflow expanding argument");
127 SS.arg = SS.aux;
128 debug("Argument expanded to %s", SS.arg);
129 return len;