📄 ls.c
字号:
#include <config.h>#include "ftpd.h"#include "ls_p.h"#include "bsd-glob.h"#include "messages.h"#include "dynamic.h"#include "ftpwho-update.h"#include "globals.h"#ifdef WITH_DMALLOC# include <dmalloc.h>#endifstatic void wrstr(const int f, const char *s){ static char outbuf[CONF_TCP_SO_SNDBUF]; static size_t outcnt; size_t l; if (s == NULL) { if (outcnt > (size_t) 0U) { if (safe_write(f, outbuf, outcnt) != 0) { return; } } outcnt = (size_t) 0U; return; } if ((l = strlen(s)) <= (size_t) 0U) { return; } if (l <= (sizeof outbuf - outcnt)) { memcpy(outbuf + outcnt, s, l); /* secure, see above */ outcnt += l; return; } if (outcnt < sizeof outbuf) { const size_t rest = sizeof outbuf - outcnt; memcpy(outbuf + outcnt, s, rest); /* secure, see above */ s += rest; l -= rest; } if (safe_write(f, outbuf, sizeof outbuf) != 0) { return; } while (l > sizeof outbuf) { if (safe_write(f, s, sizeof outbuf) != 0) { return; } s += sizeof outbuf; l -= sizeof outbuf; } if (l > (size_t) 0U) { memcpy(outbuf, s, l); /* safe, l <= sizeof outbuf */ outcnt = l; }}#ifdef NO_FTP_USERSconst char *getname(const uid_t uid){ static char number[9]; if (SNCHECK(snprintf(number, sizeof number, "%-8d", uid), sizeof number)) { _EXIT(EXIT_FAILURE); } return number;}const char *getgroup(const gid_t gid){ static char number[9]; if (SNCHECK(snprintf(number, sizeof number, "%-8d", gid), sizeof number)) { _EXIT(EXIT_FAILURE); } return number;}#elseconst char *getname(const uid_t uid){ struct userid *p; struct passwd *pwd = NULL; for (p = user_head; p; p = p->next) { if (p->uid == uid) { return p->name; } } if (# ifndef ALWAYS_RESOLVE_IDS chrooted == 0 && # endif authresult.slow_tilde_expansion == 0) { pwd = getpwuid(uid); } if ((p = malloc(sizeof *p)) == NULL) { die_mem(); } p->uid = uid; if ((p->name = malloc((size_t) 9U)) == NULL) { die_mem(); } if (pwd != NULL) { if (SNCHECK(snprintf(p->name, (size_t) 9U, "%-8.8s", pwd->pw_name), (size_t) 9U)) { _EXIT(EXIT_FAILURE); } } else { if (SNCHECK(snprintf(p->name, (size_t) 9U, "%-8d", uid), (size_t) 9U)) { _EXIT(EXIT_FAILURE); } } p->next = user_head; user_head = p; return p->name;}/* eeeehm... sorry for names, ya know copy&paste :))) */const char *getgroup(const gid_t gid){ struct groupid *p; struct group *pwd = NULL; for (p = group_head; p; p = p->next) { if (p->gid == gid) { return p->name; } } # ifndef ALWAYS_RESOLVE_IDS if (chrooted == 0) # endif { pwd = getgrgid(gid); } if ((p = malloc(sizeof *p)) == NULL) { die_mem(); } p->gid = gid; if ((p->name = malloc((size_t) 9U)) == NULL) { die_mem(); } if (pwd != NULL) { if (SNCHECK(snprintf(p->name, (size_t) 9U, "%-8.8s", pwd->gr_name), (size_t) 9U)) { _EXIT(EXIT_FAILURE); } } else { if (SNCHECK(snprintf(p->name, (size_t) 9U, "%-8d", gid), (size_t) 9U)) { _EXIT(EXIT_FAILURE); } } p->next = group_head; group_head = p; return p->name;}#endifstatic void addfile(const char *name, const char *suffix){ struct filename *p; unsigned int l; if (!name || !suffix) { return; } if (matches >= max_ls_files) { return; } matches++; l = (unsigned int) (strlen(name) + strlen(suffix)); if (l > colwidth) { colwidth = l; } if ((p = malloc(offsetof(struct filename, line) + l + 1U)) == NULL) { return; } if (SNCHECK(snprintf(p->line, l + 1U, "%s%s", name, suffix), l + 1U)) { _EXIT(EXIT_FAILURE); } if (tail != NULL) { tail->down = p; } else { head = p; } tail = p; filenames++;}/* listfile returns non-zero if the file is a directory */static int listfile(const FileInfo * const fi, const char *name){ int rval = 0; struct stat st; struct tm *t; char suffix[2] = { 0, 0 }; char m[MAXPATHLEN + 1U]; #ifndef MINIMAL if (modern_listings != 0) { const char *n; char *alloca_nameline; const size_t sizeof_nameline = MAXPATHLEN + 256U; if (fi == NULL) { n = name; } else { n = FI_NAME(fi); } if ((alloca_nameline = ALLOCA(sizeof_nameline)) == NULL) { return 0; } if ((rval = modernformat(n, alloca_nameline, sizeof_nameline)) < 0) { ALLOCA_FREE(alloca_nameline); return 0; } addfile(alloca_nameline, suffix); ALLOCA_FREE(alloca_nameline); return rval; }#endif if (fi == NULL) { if (lstat(name, &st) < 0) { return 0; } } else { st.st_size = fi->size; st.st_mtime = fi->mtime; st.st_mode = fi->mode; st.st_nlink = fi->nlink; st.st_uid = fi->uid; st.st_gid = fi->gid; name = FI_NAME(fi); }#if defined(WITH_VIRTUAL_CHROOT) && defined(S_IFLNK) && defined(S_IFDIR) if (S_ISLNK(st.st_mode) && name[0] == '.' && name[1] == '.' && name[2] == 0) { st.st_mode &= ~S_IFLNK; st.st_mode |= S_IFDIR; } /* Hack to please some Windows client that dislike ../ -> ../ */#endif#ifdef DISPLAY_FILES_IN_UTC_TIME t = gmtime((time_t *) &st.st_mtime);#else t = localtime((time_t *) &st.st_mtime);#endif if (t == NULL) { logfile(LOG_ERR, "{gm,local}gtime() for [%s]", name); return 0; } if (opt_F) { if (S_ISLNK(st.st_mode)) suffix[0] = '@'; else if (S_ISDIR(st.st_mode)) { suffix[0] = '/'; rval = 1; } else if (st.st_mode & 010101) { suffix[0] = '*'; } } if (opt_l) { strncpy(m, " ---------", (sizeof m) - (size_t) 1U); m[(sizeof m) - (size_t) 1U] = 0; switch (st.st_mode & S_IFMT) { case S_IFREG: m[0] = '-'; break; case S_IFLNK: m[0] = 'l'; break; /* readlink() here? */ case S_IFDIR: m[0] = 'd'; rval = 1; break; } if (m[0] != ' ') { char *alloca_nameline; const size_t sizeof_nameline = MAXPATHLEN + MAXPATHLEN + 128U; char timeline[6U]; if (st.st_mode & 0400) { m[1] = 'r'; } if (st.st_mode & 0200) { m[2] = 'w'; } if (st.st_mode & 0100) { m[3] = (char) (st.st_mode & 04000 ? 's' : 'x'); } else if (st.st_mode & 04000) { m[3] = 'S'; } if (st.st_mode & 040) { m[4] = 'r'; } if (st.st_mode & 020) { m[5] = 'w'; } if (st.st_mode & 010) { m[6] = (char) (st.st_mode & 02000 ? 's' : 'x'); } else if (st.st_mode & 02000) { m[6] = 'S'; } if (st.st_mode & 04) { m[7] = 'r'; } if (st.st_mode & 02) { m[8] = 'w'; } if (st.st_mode & 01) { m[9] = (char) (st.st_mode & 01000 ? 't' : 'x'); } else if (st.st_mode & 01000) { m[9] = 'T'; } if (time(NULL) - st.st_mtime > 180 * 24 * 60 * 60) { if (SNCHECK(snprintf(timeline, sizeof timeline, "%5d", t->tm_year + 1900), sizeof timeline)) { _EXIT(EXIT_FAILURE); } } else { if (SNCHECK(snprintf(timeline, sizeof timeline, "%02d:%02d", t->tm_hour, t->tm_min), sizeof timeline)) { _EXIT(EXIT_FAILURE); } } if ((alloca_nameline = ALLOCA(sizeof_nameline)) == NULL) { return 0; }#ifdef WITH_LARGE_FILES if (SNCHECK(snprintf(alloca_nameline, sizeof_nameline, "%s %4d %s %s %8llu %s %2d %s %s", m, st.st_nlink, getname(st.st_uid), getgroup(st.st_gid), (unsigned long long) st.st_size, months[t->tm_mon], t->tm_mday, timeline, name), sizeof_nameline))#else if (SNCHECK(snprintf(alloca_nameline, sizeof_nameline, "%s %4d %s %s %8lu %s %2d %s %s", m, st.st_nlink, getname(st.st_uid), getgroup(st.st_gid), (unsigned long) st.st_size, months[t->tm_mon], t->tm_mday, timeline, name), sizeof_nameline))#endif { ALLOCA_FREE(alloca_nameline); _EXIT(EXIT_FAILURE); } if (S_ISLNK(st.st_mode)) { char *p = alloca_nameline + strlen(alloca_nameline); { int sx; if ((sx = readlink(name, m, sizeof m - 1U)) > 0) { m[sx] = 0; } else { m[0] = m[1] = '.'; m[2] = 0; } } suffix[0] = 0; if (opt_F && stat(name, &st) == 0) { if (S_ISLNK(st.st_mode)) { suffix[0] = '@'; } else if (S_ISDIR(st.st_mode)) { suffix[0] = '/'; } else if (st.st_mode & 010101) { suffix[0] = '*'; } } /* 2 * MAXPATHLEN + gap should be enough, but be paranoid... */ if (SNCHECK (snprintf(p, (sizeof_nameline) - strlen(alloca_nameline), " -> %s", m), (sizeof_nameline) - strlen(alloca_nameline))) { ALLOCA_FREE(alloca_nameline); _EXIT(EXIT_FAILURE); } } addfile(alloca_nameline, suffix); ALLOCA_FREE(alloca_nameline); } /* hide non-downloadable files */ } else { if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode)) { addfile(name, suffix); } } return rval;}static void outputfiles(int f){ unsigned int n; struct filename *p; struct filename *q; if (!head) { return; } tail->down = NULL; tail = NULL; colwidth = (colwidth | 7U) + 1U; if (opt_l != 0 || opt_C == 0) { colwidth = 75U; } /* set up first column */ p = head; p->top = 1; if (colwidth > 75U) { n = filenames; } else { n = (filenames + (75U / colwidth) - 1U) / (75U / colwidth); } while (n && p) { p = p->down; if (p != NULL) { p->top = 0; } n--; } /* while there's a neighbour to the right, point at it */ q = head; while (p) { p->top = q->top; q->right = p; q = q->down; p = p->down; } /* some are at the right end */ while (q) { q->right = NULL; q = q->down; } /* don't want wraparound, do we? */ p = head; while (p && p->down && !p->down->top) { p = p->down; } if (p && p->down) { p->down = NULL; } /* print each line, which consists of each column */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -