📄 extensions.c
字号:
if (strcasecmp(q + 6, class) == 0) classmatched = 1; } else if (strcmp(q, "-") == 0) { i++; options = 0; } else options = 0; } if (!classfound || classmatched) { for (; (i < MAXARGS) && ((q = entry->arg[i]) != (char *) NULL) && (q[0] != '\0'); i++) { len = strlen(q); p = (q[0] == '/') ? whichname : lbasename(whichname); if (!wu_fnmatch(q, p, FNM_PATHNAME | FNM_LEADING_DIR)) { if (!allow_retrieve(name)) {#ifdef VERBOSE_ERROR_LOGING syslog(LOG_NOTICE, "%s of %s tried to download %s", pw->pw_name, remoteident, realname);#endif reply(550, "%s is marked unretrievable", localname); return 1; } } } } } return 0;}#ifdef QUOTA#ifndef MNTMAXSTR#define MNTMAXSTR 2048 /* And hope it's enough */#endif#ifdef QUOTA_DEVICEint path_to_device(char *pathname, char *result){ FILE *fp;#ifdef HAS_OLDSTYLE_GETMNTENT struct mnttab static_mp; struct mnttab *mp = &static_mp;#else struct mntent *mp;#endif struct mount_ent { char mnt_fsname[MNTMAXSTR], mnt_dir[MNTMAXSTR]; struct mount_ent *next; } mountent; struct mount_ent *current, *start, *new; char path[1024], mnt_dir[1024], *pos; int flag = 1; extern char chroot_path[]; start = current = NULL;#ifdef HAS_OLDSTYLE_GETMNTENT fp = fopen(MNTTAB, "r");#else fp = setmntent(MNTTAB, "r");#endif if (fp == NULL) return 0;#ifdef HAS_OLDSTYLE_GETMNTENT while (getmntent(fp, &static_mp) == 0)#else while (mp = getmntent(fp))#endif { if (!(new = (struct mount_ent *) malloc(sizeof(mountent)))) { perror("malloc"); flag = 0; break; } if (!start) start = current = new; else current = current->next = new;#ifdef HAS_OLDSTYLE_GETMNTENT strncpy(current->mnt_fsname, mp->mnt_special, strlen(mp->mnt_special) + 1); strncpy(current->mnt_dir, mp->mnt_mountp, strlen(mp->mnt_mountp) + 1);#else strncpy(current->mnt_fsname, mp->mnt_fsname, strlen(mp->mnt_fsname) + 1); strncpy(current->mnt_dir, mp->mnt_dir, strlen(mp->mnt_dir) + 1);#endif }#ifdef HAS_OLDSTYLE_GETMNTENT fclose(fp);#else endmntent(fp);#endif current->next = NULL; wu_realpath(pathname, path, chroot_path); while (*path && flag) { current = start; while (current && flag) { if (strcmp(current->mnt_dir, "swap")) { wu_realpath(current->mnt_dir, mnt_dir, chroot_path); if (!strcmp(mnt_dir, path)) { flag = 0; /* no support for remote quota yet */ if (!strchr(current->mnt_fsname, ':')) strcpy(result, current->mnt_fsname); } } current = current->next; } if (!((pos = strrchr(path, '/')) - path) && strlen(path) > 1) strcpy(path, "/"); else path[pos - path] = '\0'; } while (current) { new = current->next; free(current); current = new; } return 1;}#endifvoid get_quota(char *fs, int uid){ char mnt_fsname[MNTMAXSTR];#ifdef HAS_NO_QUOTACTL int dirfd; struct quotctl qp; if (path_to_device(fs, mnt_fsname)) { dirfd = open(fs, O_RDONLY); qp.op = Q_GETQUOTA; qp.uid = uid; qp.addr = (char *) "a; ioctl(dirfd, Q_QUOTACTL, &qp); close(dirfd); }#else#ifdef QUOTA_DEVICE if (path_to_device(fs, mnt_fsname))#ifdef QCMD quotactl(QCMD(Q_GETQUOTA, USRQUOTA), mnt_fsname, uid, (char *) "a);#else quotactl(Q_GETQUOTA, mnt_fsname, uid, (char *) "a);#endif#else quotactl(fs, QCMD(Q_GETQUOTA, USRQUOTA), uid, (char *) "a);#endif#endif /* HAS_NO_QUOTACTL */}char *time_quota(long curstate, long softlimit, long timelimit, char *timeleft){ struct timeval tv; gettimeofday(&tv, NULL); if (softlimit && curstate >= softlimit) { if (timelimit == 0) { strcpy(timeleft, "NOT STARTED"); } else if (timelimit > tv.tv_sec) { fmttime(timeleft, timelimit - tv.tv_sec); } else { strcpy(timeleft, "EXPIRED"); } } else { timeleft[0] = '\0'; } return (timeleft);}void fmttime(char *buf, register long time){ int i; static struct { int c_secs; /* conversion units in secs */ char *c_str; /* unit string */ } cunits[] = { { 60 *60 * 24 * 28, "months" } , { 60 *60 * 24 * 7, "weeks" } , { 60 *60 * 24, "days" } , { 60 *60, "hours" } , { 60, "mins" } , { 1, "secs" } }; if (time <= 0) { strcpy(buf, "EXPIRED"); return; } for (i = 0; i < sizeof(cunits) / sizeof(cunits[0]); i++) { if (time >= cunits[i].c_secs) break; } sprintf(buf, "%.1f %s", (double) time / cunits[i].c_secs, cunits[i].c_str);}#endif#ifdef QUOTA#if (defined(LINUX) && !defined(AUTOCONF)) || (defined(AUTOCONF) && !defined(HAVE_QUOTACTL) && defined(__linux__))/* I have no idea why I can't find 'quotactl()' in my libs, here's the source - GAL *//* This was a bug in truly ancient libc's (prior to 5.3.something). It isn't needed on any modern version of Linux. *//* * QUOTA An implementation of the diskquota system for the LINUX * operating system. QUOTA is implemented using the BSD systemcall * interface as the means of communication with the user level. * Should work for all filesystems because of integration into the * VFS layer of the operating system. * This is based on the Melbourne quota system wich uses both user and * group quota files. * * System call interface. * * Version: $Id: extensions.c,v 1.48 2000/07/01 18:17:38 wuftpd Exp $ * * Author: Marco van Wieringen <mvw@planets.ow.nl> <mvw@tnix.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */#if defined(__alpha__)#include <errno.h>#include <sys/types.h>#include <syscall.h>#include <asm/unistd.h>int quotactl(int cmd, const char *special, int id, caddr_t addr){ return syscall(__NR_quotactl, cmd, special, id, addr);}#else /* __alpha__ */#include <sys/types.h>#define __LIBRARY__#include <linux/unistd.h>_syscall4(int, quotactl, int, cmd, const char *, special, int, id, caddr_t, addr);#endif /* __alpha__ */#elif !defined(HAVE_QUOTACTL) /* LINUX */#ifdef QUOTA_DEVICE/* I have no idea why I can't find 'quotactl()' in my libs, here's the source - keller */int quotactl(int cmd, const char *special, int id, caddr_t addr){ struct quotctl { int op; uid_t uid; caddr_t addr; } qp; /* * open up the quota file in the root directory to get the file descriptor. * if no quota file exists, quotas are not enabled. */ FILE *qf; char mnt_pnt[1024]; mnt_pnt[0] = '\0'; strncpy(mnt_pnt, special, strlen(mnt_pnt)); strncat(mnt_pnt, "/quota", strlen(mnt_pnt)); qf = fopen(mnt_pnt, "r"); if (qf == NULL) return(-1); qp.op = Q_GETQUOTA; qp.uid = id; qp.addr = addr; return ioctl((int) qf, (int) Q_QUOTACTL, qp);}#endif /* QUOTA_DEVICE */#endif /* LINUX */#endif /* QUOTA */#ifdef THROUGHPUTint file_compare(char *patterns, char *file){ char buf[MAXPATHLEN]; char *cp; char *cp2; int i; int matches = 0; strncpy(buf, patterns, sizeof(buf)); buf[sizeof(buf) - 1] = '\0'; i = strlen(buf); buf[i++] = ','; buf[i++] = '\0'; cp = buf; while ((cp2 = strchr(cp, ',')) != NULL) { *cp2++ = '\0'; if (wu_fnmatch(cp, file, FNM_PATHNAME) == 0) { matches = 1; break; } } return matches;}int remote_compare(char *patterns){ char buf[MAXPATHLEN]; char *cp; char *cp2; int i; int matches = 0; strncpy(buf, patterns, sizeof(buf)); buf[sizeof(buf) - 1] = '\0'; i = strlen(buf); buf[i++] = ','; buf[i++] = '\0'; cp = buf; while ((cp2 = strchr(cp, ',')) != NULL) { *cp2++ = '\0'; if (hostmatch(cp, remoteaddr, remotehost)) { matches = 1; break; } } return matches;}void throughput_calc(char *name, int *bps, double *bpsmult){ int match_value = -1; char cwdir[MAXPATHLEN]; char pwdir[MAXPATHLEN]; char path[MAXPATHLEN]; char file[MAXPATHLEN]; char *ap3 = NULL, *ap4 = NULL; struct aclmember *entry = NULL; extern char *home; extern char chroot_path[]; char *sp; int i; /* default is maximum throughput */ *bps = -1; *bpsmult = 1.0; /* XXX We could use dynamic RAM to store this path, but I'd rather just bail out with an error. The rest of wu is so crufy that a long path might just blow up later */ if ((strlen(name) + 1) > sizeof(path)) { return; } /* what's our current directory? */ strcpy(path, name); if ((sp = strrchr(path, '/'))) *sp = '\0'; else strcpy(path, "."); if ((sp = strrchr(name, '/'))) strcpy(file, sp + 1); else strcpy(file, name); if ((fb_realpath(path, cwdir)) == NULL) { return; } wu_realpath(home, pwdir, chroot_path); /* find best matching entry */ while (getaclentry("throughput", &entry) && ARG0 && ARG1 && ARG2 && ARG3 && ARG4 && ARG5 != NULL) { if ((0 < path_compare(ARG0, pwdir)) && ((i = path_compare(ARG1, cwdir)) >= match_value) ) { if (file_compare(ARG2, file)) { if (remote_compare(ARG5)) { match_value = i; ap3 = ARG3; ap4 = ARG4; } } } } /* if we did get matches */ if (match_value >= 0) { if (strcasecmp(ap3, "oo") == 0) *bps = -1; else *bps = atoi(ap3); if (strcmp(ap4, "-") == 0) *bpsmult = 1.0; else *bpsmult = atof(ap4); } return;}void throughput_adjust(char *name){ int match_value = -1; char pwdir[MAXPATHLEN]; char cwdir[MAXPATHLEN]; char path[MAXPATHLEN]; char file[MAXPATHLEN]; char buf[MAXPATHLEN]; char *ap3 = NULL, *ap4 = NULL; char **pap3; struct aclmember *entry = NULL; extern char *home; extern char chroot_path[]; char *sp; int i; /* XXX We could use dynamic RAM to store this path, but I'd rather just bail out with an error. The rest of wu is so crufy that a long path might just blow up later */ if ((strlen(name) + 1) > sizeof(path)) { return; } /* what's our current directory? */ strcpy(path, name); if ((sp = strrchr(path, '/'))) *sp = '\0'; else strcpy(path, "."); if ((sp = strrchr(name, '/'))) strcpy(file, sp + 1); else strcpy(file, name); if ((fb_realpath(path, cwdir)) == NULL) { return; } wu_realpath(home, pwdir, chroot_path); /* find best matching entry */ while (getaclentry("throughput", &entry) && ARG0 && ARG1 && ARG2 && ARG3 && ARG4 && ARG5 != NULL) { if ((0 < path_compare(ARG0, pwdir)) && ((i = path_compare(ARG1, cwdir)) >= match_value) ) { if (file_compare(ARG2, file)) { if (remote_compare(ARG5)) { match_value = i; ap3 = ARG3; pap3 = &ARG3; ap4 = ARG4; } } } } /* if we did get matches */ if (match_value >= 0) { if (strcasecmp(ap3, "oo") != 0) { if (strcmp(ap4, "-") != 0) { sprintf(buf, "%.0f", atoi(ap3) * atof(ap4)); *pap3 = (char *) malloc(strlen(buf) + 1); if (*pap3 == NULL) { syslog(LOG_ERR, "malloc error in throughput_adjust"); exit(0); } strcpy(*pap3, buf); } } } return;}#endifstatic int CheckMethod = 0;void SetCheckMethod(const char *method){ if ((strcasecmp(method, "md5") == 0) || (strcasecmp(method, "rfc1321") == 0)) CheckMethod = 0; else if ((strcasecmp(method, "crc") == 0) || (strcasecmp(method, "posix") == 0)) CheckMethod = 1; else { reply(500, "Unrecognized checksum method"); return; } switch (CheckMethod) { default: reply(200, "Checksum method is now: MD5 (RFC1321)"); break; case 1: reply(200, "Checksum method is now: CRC (POSIX)"); break; }}void ShowCheckMethod(void){ switch (CheckMethod) { default: reply(200, "Current checksum method: MD5 (RFC1321)"); break; case 1: reply(200, "Current checksum method: CRC (POSIX)"); break; }}void CheckSum(char *pathname){ char *cmd; char buf[MAXPATHLEN]; FILE *cmdf; struct stat st; if (stat(pathname, &st) == 0) { if ((st.st_mode & S_IFMT) != S_IFREG) { reply(500, "%s: not a plain file.", pathname); return; } } else { perror_reply(550, pathname); return; } switch (CheckMethod) { default: cmd = "/bin/md5sum"; break; case 1: cmd = "/bin/cksum"; break; } if (strlen(cmd) + 1 + strlen(pathname) + 1 > sizeof(buf)) { reply(500, "Pathname too long"); return; } sprintf(buf, "%s %s", cmd, pathname); cmdf = ftpd_popen(buf, "r", 0); if (!cmdf) { perror_reply(550, cmd); } else { if (fgets(buf, sizeof buf, cmdf)) { char *crptr = strchr(buf, '\n'); if (crptr != NULL) *crptr = '\0'; reply(200, "%s", buf); } ftpd_pclose(cmdf); }}void CheckSumLastFile(void){ extern char LastFileTransferred[]; if (LastFileTransferred[0] == '\0') reply(500, "Nothing transferred yet"); else CheckSum(LastFileTransferred);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -