Index: modules/mod_ls.c =================================================================== RCS file: /cvsroot/proftp/proftpd/modules/mod_ls.c,v retrieving revision 1.187 diff -u -r1.187 mod_ls.c --- modules/mod_ls.c 5 Nov 2011 23:01:58 -0000 1.187 +++ modules/mod_ls.c 1 Feb 2012 18:57:20 -0000 @@ -81,6 +81,7 @@ /* ls options */ static int + opt_1 = 0, opt_a = 0, opt_A = 0, opt_B = 0, @@ -395,7 +396,6 @@ p = cmd->tmp_pool; if (pr_fsio_lstat(name, &st) == 0) { - char *display_name = NULL; suffix[0] = suffix[1] = '\0'; @@ -493,21 +493,24 @@ break; } - if (list_times_gmt) + if (list_times_gmt) { t = pr_gmtime(p, (time_t *) &sort_time); - else + + } else { t = pr_localtime(p, (time_t *) &sort_time); + } if (opt_F) { - if (S_ISLNK(st.st_mode)) + if (S_ISLNK(st.st_mode)) { suffix[0] = '@'; - else if (S_ISDIR(st.st_mode)) { + } else if (S_ISDIR(st.st_mode)) { suffix[0] = '/'; rval = 1; - } else if (st.st_mode & 0111) + } else if (st.st_mode & 0111) { suffix[0] = '*'; + } } if (opt_l) { @@ -576,32 +579,38 @@ m[2] = (mode & S_IWUSR) ? 'w' : '-'; m[1] = (mode & S_IRUSR) ? 'r' : '-'; - if (ls_curtime - sort_time > 180 * 24 * 60 * 60) + if (ls_curtime - sort_time > 180 * 24 * 60 * 60) { snprintf(timeline, sizeof(timeline), "%5d", t->tm_year+1900); - else + } else { snprintf(timeline, sizeof(timeline), "%02d:%02d", t->tm_hour, t->tm_min); + } ls_fmt_filesize(s, sizeof(s), st.st_size); - if (!opt_n) { - - /* Format nameline using user/group names. */ - snprintf(nameline, sizeof(nameline)-1, - "%s %3d %-8s %-8s %s %s %2d %s %s", m, (int) st.st_nlink, - MAP_UID(st.st_uid), MAP_GID(st.st_gid), s, - months[t->tm_mon], t->tm_mday, timeline, + if (opt_1) { + /* One file per line, with no info other than the file name. Easy. */ + snprintf(nameline, sizeof(nameline)-1, "%s", pr_fs_encode_path(cmd->tmp_pool, display_name)); } else { - - /* Format nameline using user/group IDs. */ - snprintf(nameline, sizeof(nameline)-1, - "%s %3d %-8u %-8u %s %s %2d %s %s", m, (int) st.st_nlink, - (unsigned) st.st_uid, (unsigned) st.st_gid, s, - months[t->tm_mon], t->tm_mday, timeline, - pr_fs_encode_path(cmd->tmp_pool, name)); + if (!opt_n) { + /* Format nameline using user/group names. */ + snprintf(nameline, sizeof(nameline)-1, + "%s %3d %-8s %-8s %s %s %2d %s %s", m, (int) st.st_nlink, + MAP_UID(st.st_uid), MAP_GID(st.st_gid), s, + months[t->tm_mon], t->tm_mday, timeline, + pr_fs_encode_path(cmd->tmp_pool, display_name)); + + } else { + /* Format nameline using user/group IDs. */ + snprintf(nameline, sizeof(nameline)-1, + "%s %3d %-8u %-8u %s %s %2d %s %s", m, (int) st.st_nlink, + (unsigned) st.st_uid, (unsigned) st.st_gid, s, + months[t->tm_mon], t->tm_mday, timeline, + pr_fs_encode_path(cmd->tmp_pool, name)); + } } nameline[sizeof(nameline)-1] = '\0'; @@ -611,40 +620,45 @@ suffix[0] = '\0'; if (opt_F && pr_fsio_stat(name, &st) == 0) { - if (S_ISLNK(st.st_mode)) + if (S_ISLNK(st.st_mode)) { suffix[0] = '@'; - else if (S_ISDIR(st.st_mode)) + } else if (S_ISDIR(st.st_mode)) { suffix[0] = '/'; - else if (st.st_mode & 0111) + } else if (st.st_mode & 0111) { suffix[0] = '*'; + } } if (!opt_L && list_show_symlinks) { - if (sizeof(nameline) - strlen(nameline) > 4) + if (sizeof(nameline) - strlen(nameline) > 4) { snprintf(buf, sizeof(nameline) - strlen(nameline) - 4, " -> %s", l); - else + } else { pr_log_pri(PR_LOG_NOTICE, "notice: symlink '%s' yields an " "excessive string, ignoring", name); + } } nameline[sizeof(nameline)-1] = '\0'; } - if (opt_STAT) + if (opt_STAT) { pr_response_add(R_211, "%s%s", nameline, suffix); - else + + } else { addfile(cmd, nameline, suffix, sort_time, st.st_size); + } } } else { if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || - S_ISLNK(st.st_mode)) + S_ISLNK(st.st_mode)) { addfile(cmd, pr_fs_encode_path(cmd->tmp_pool, name), suffix, sort_time, st.st_size); + } } } @@ -1302,6 +1316,7 @@ switch (**opt) { case '1': if (strcmp(session.curr_cmd, C_STAT) != 0) { + opt_1 = 1; opt_l = opt_C = 0; } break; @@ -1354,6 +1369,7 @@ if (strcmp(session.curr_cmd, C_NLST) != 0) { opt_l = 1; opt_C = 0; + opt_1 = 0; } break; @@ -1422,7 +1438,7 @@ while ((*opt)++ && isalnum((int) **opt)) { switch (**opt) { case '1': - opt_l = opt_C = 0; + opt_1 = opt_l = opt_C = 0; break; case 'A': @@ -1571,8 +1587,8 @@ ls_curtime = time(NULL); if (clearflags) { - opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_h = opt_n = opt_r = - opt_R = opt_S = opt_t = opt_STAT = opt_L = 0; + opt_1 = opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_h = opt_n = + opt_r = opt_R = opt_S = opt_t = opt_STAT = opt_L = 0; } if (have_options(cmd, arg)) { @@ -1671,8 +1687,10 @@ /* Open data connection */ if (!opt_STAT) { - if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) + if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) { return -1; + } + session.sf_flags |= SF_ASCII_OVERRIDE; } @@ -1705,7 +1723,6 @@ skiparg = TRUE; } else { - skiparg = FALSE; if (use_globbing && @@ -1945,6 +1962,10 @@ return -1; } + /* XXX Note that "NLST " was sent, we might be receiving paths + * here, not just file names. And that is not what dir_hide_file() is + * expecting. + */ if (dir_hide_file(file)) return 1; @@ -1970,6 +1991,25 @@ } #endif /* PR_USE_NLS */ + if (opt_1) { + char *ptr; + + /* If the -1 option is configured, we want to make sure that we only + * display a file, not a path. And it's possible that we given a path + * here. + */ + ptr = strrchr(display_name, '/'); + if (ptr != NULL) { + size_t display_namelen; + + display_namelen = strlen(display_name); + if (display_namelen > 1) { + /* Make sure that we handle a possible display_name of '/' properly. */ + display_name = ptr + 1; + } + } + } + /* Be sure to flush the output */ res = sendline(0, "%s\n", pr_fs_encode_path(cmd->tmp_pool, display_name)); if (res < 0) @@ -2098,8 +2138,16 @@ continue; if (!curdir) { - char *str = pr_fs_encode_path(cmd->tmp_pool, - pdircat(cmd->tmp_pool, dir, p, NULL)); + char *str = NULL; + + if (opt_1) { + /* Send just the file name, not the path. */ + str = pr_fs_encode_path(cmd->tmp_pool, p); + + } else { + str = pr_fs_encode_path(cmd->tmp_pool, + pdircat(cmd->tmp_pool, dir, p, NULL)); + } if (sendline(0, "%s\n", str) < 0) { count = -1; @@ -2204,26 +2252,32 @@ fakeuser = get_param_ptr(CURRENT_CONF, "DirFakeUser", FALSE); /* Check for a configured "logged in user" DirFakeUser. */ - if (fakeuser && strcmp(fakeuser, "~") == 0) + if (fakeuser != NULL && + strcmp(fakeuser, "~") == 0) { fakeuser = session.user; + } fakegroup = get_param_ptr(CURRENT_CONF, "DirFakeGroup", FALSE); /* Check for a configured "logged in user" DirFakeGroup. */ - if (fakegroup && strcmp(fakegroup, "~") == 0) + if (fakegroup != NULL && + strcmp(fakegroup, "~") == 0) { fakegroup = session.group; + } fake_mode = get_param_ptr(CURRENT_CONF, "DirFakeMode", FALSE); if (fake_mode) { fakemode = *fake_mode; have_fake_mode = TRUE; - } else + } else { have_fake_mode = FALSE; + } tmp = get_param_ptr(TOPLEVEL_CONF, "TimesGMT", FALSE); - if (tmp != NULL) + if (tmp != NULL) { list_times_gmt = *tmp; + } res = dolist(cmd, pr_fs_decode_path(cmd->tmp_pool, cmd->arg), TRUE); @@ -2231,8 +2285,9 @@ pr_data_abort(0, 0); res = -1; - } else if (session.sf_flags & SF_XFER) + } else if (session.sf_flags & SF_XFER) { ls_done(cmd); + } opt_l = 0; @@ -2415,8 +2470,9 @@ list_nfiles.logged = list_ndirs.logged = list_ndepth.logged = FALSE; tmp = get_param_ptr(TOPLEVEL_CONF, "ShowSymlinks", FALSE); - if (tmp != NULL) + if (tmp != NULL) { list_show_symlinks = *tmp; + } target = cmd->argc == 1 ? "." : pr_fs_decode_path(cmd->tmp_pool, cmd->arg); @@ -2444,8 +2500,8 @@ } /* Clear the listing option flags. */ - opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_n = opt_r = opt_R = - opt_S = opt_t = opt_STAT = opt_L = 0; + opt_1 = opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_n = opt_r = + opt_R = opt_S = opt_t = opt_STAT = opt_L = 0; if (have_options(cmd, target)) { if (!list_strict_opts) { @@ -2602,8 +2658,10 @@ } else { if (list_flags & LS_FL_NO_ERROR_IF_ABSENT) { - if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) + if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) { return PR_ERROR(cmd); + } + session.sf_flags |= SF_ASCII_OVERRIDE; pr_response_add(R_226, _("Transfer complete")); ls_done(cmd); @@ -2617,8 +2675,10 @@ } else { if (list_flags & LS_FL_NO_ERROR_IF_ABSENT) { - if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) + if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) { return PR_ERROR(cmd); + } + session.sf_flags |= SF_ASCII_OVERRIDE; pr_response_add(R_226, _("Transfer complete")); ls_done(cmd); @@ -2631,8 +2691,10 @@ } } - if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) + if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) { return PR_ERROR(cmd); + } + session.sf_flags |= SF_ASCII_OVERRIDE; /* Iterate through each matching entry */