Skip to content

Commit db2c2f7

Browse files
authored
Better MLST symlink support, CWD file type check
- MLSD/MLST now report symlink targets. - CWD now checks if the argument is a directory.
1 parent 1a592e4 commit db2c2f7

File tree

2 files changed

+41
-23
lines changed

2 files changed

+41
-23
lines changed

source/ftp.c

+40-22
Original file line numberDiff line numberDiff line change
@@ -278,27 +278,37 @@ static int send_facts(struct client_info *client, char *path, char *filename,
278278
return -1;
279279

280280
char *type;
281+
char type_slink_buf[20 + PATH_MAX];
281282
if (client->facts.type) {
282-
if (S_ISDIR(statbuf.st_mode)) {
283+
if (S_ISREG(statbuf.st_mode)) {
284+
type = "type=file;";
285+
} else if (S_ISDIR(statbuf.st_mode)) {
283286
if (filename[0] == '.' && filename[1] == '\0')
284287
type = "type=cdir;";
285288
else if (filename[0] == '.' && filename[1] == '.'
286289
&& filename[2] == '\0')
287290
type = "type=pdir;";
288291
else
289292
type = "type=dir;";
290-
} else if (S_ISREG(statbuf.st_mode)) {
291-
type = "type=file;";
292293
} else if (S_ISLNK(statbuf.st_mode)) {
293-
type = "type=os.unix=slink;";
294+
type = "type=OS.unix=slink:";
295+
strcpy(type_slink_buf, type);
296+
int ret = readlink(path, type_slink_buf + strlen(type), PATH_MAX);
297+
if (ret < 0 || ret == PATH_MAX) {
298+
debug_retval(ret);
299+
strcpy(type_slink_buf + strlen(type) - 1, ";");
300+
} else {
301+
strcpy(type_slink_buf + strlen(type) + ret, ";");
302+
}
303+
type = type_slink_buf;
294304
} else if (S_ISCHR(statbuf.st_mode)) {
295-
type = "type=os.unix=cdevice;";
305+
type = "type=OS.unix=cdevice;";
296306
} else if (S_ISBLK(statbuf.st_mode)) {
297-
type = "type=os.unix=bdevice;";
307+
type = "type=OS.unix=bdevice;";
298308
} else if (S_ISFIFO(statbuf.st_mode)) {
299-
type = "type=os.unix=fifo;";
309+
type = "type=OS.unix=fifo;";
300310
} else if (S_ISSOCK(statbuf.st_mode)) {
301-
type = "type=os.unix=socket;";
311+
type = "type=OS.unix=socket;";
302312
} else {
303313
type = "type=file;";
304314
}
@@ -541,30 +551,38 @@ static void cmd_CWD(struct client_info *client)
541551
{
542552
if (strcmp(client->cmd_args, "..") == 0) {
543553
if (dir_up(client))
544-
send_ctrl_msg(client, RC_550);
554+
goto reject;
545555
else
546-
send_ctrl_msg(client, RC_250);
547-
return;
556+
goto accept;
548557
}
549558
if (strcmp(client->cmd_args, ".") == 0)
550559
client->cmd_args = client->cur_path;
551560

552561
char path[PATH_MAX];
553-
if (gen_ftp_path(path, sizeof(path), client, client->cmd_args)) {
554-
send_ctrl_msg(client, RC_550);
555-
return;
556-
}
562+
if (gen_ftp_path(path, sizeof(path), client, client->cmd_args))
563+
goto reject;
557564

558565
#ifdef PS4
559-
if (ftp_file_exists(path)) {
566+
if (!ftp_file_exists(path))
560567
#else
561-
if (access(path, R_OK) == 0) {
568+
if (access(path, R_OK) != 0)
562569
#endif
563-
strncpy(client->cur_path, path, sizeof(client->cur_path));
564-
send_ctrl_msg(client, RC_250);
565-
} else {
566-
send_ctrl_msg(client, RC_550);
567-
}
570+
goto reject;
571+
572+
struct stat st;
573+
int ret = stat(path, &st);
574+
if (ret || !S_ISDIR(st.st_mode))
575+
goto reject;
576+
577+
strncpy(client->cur_path, path, sizeof(client->cur_path));
578+
goto accept;
579+
580+
reject:
581+
send_ctrl_msg(client, RC_550);
582+
return;
583+
584+
accept:
585+
send_ctrl_msg(client, RC_250);
568586
}
569587

570588
// DELE (Delete) "DELE <SP> <pathname> <CRLF>" ---------------------------------

source/ftp.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#define FILE_BUF_SIZE 8192
1212
#define DEFAULT_PATH "/"
1313
#define DEFAULT_PORT 1337
14-
#define RELEASE_VERSION "v1.08c BETA"
14+
#define RELEASE_VERSION "v1.08c (WIP)"
1515

1616
// Uncomment this line or use compiler option -DNO_MLST to prevent the FTP
1717
// server from advertising MLST capability in response to a FEAT command.

0 commit comments

Comments
 (0)