📄 ftp.c
字号:
rc = -1;
switch (curtype) {
case TYPE_A:
rc = fseek(fin, (long) restart_point, SEEK_SET);
break;
case TYPE_I:
case TYPE_L:
rc = (int)lseek(fileno(fin), restart_point, SEEK_SET); /* cast added for EFI port */
break;
}
if (rc < 0) {
warn("local: %s", local);
if (closefunc != NULL)
(*closefunc)(fin);
goto cleanupsend;
}
if (command("REST %qd", (__int64_t) restart_point) != /* replaced long long for EFI port */
CONTINUE) {
if (closefunc != NULL)
(*closefunc)(fin);
goto cleanupsend;
}
lmode = "r+w";
}
if (remote) {
if (command("%s %s", cmd, remote) != PRELIM) {
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
if (oldintp)
(void)signal(SIGPIPE, oldintp);
if (closefunc != NULL)
(*closefunc)(fin);
goto cleanupsend;
}
} else
if (command("%s", cmd) != PRELIM) {
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
if (oldintp)
(void)signal(SIGPIPE, oldintp);
if (closefunc != NULL)
(*closefunc)(fin);
goto cleanupsend;
}
dout = dataconn(lmode);
if (dout == NULL)
goto abort;
progressmeter(-1);
oldintp = signal(SIGPIPE, SIG_IGN);
switch (curtype) {
case TYPE_I:
case TYPE_L:
errno = d = 0;
while ((c = (int)read(fileno(fin), buf, sizeof(buf))) > 0) {
bytes += c;
for (bufp = buf; c > 0; c -= d, bufp += d)
if ((d = (int)write(fileno(dout), bufp, c)) <= 0)
break;
if (hash && (!progress || filesize < 0) ) {
while (bytes >= hashbytes) {
(void)putchar('#');
hashbytes += mark;
}
(void)fflush(stdout);
}
}
if (hash && (!progress || filesize < 0) && bytes > 0) {
if (bytes < mark)
(void)putchar('#');
(void)putchar('\n');
(void)fflush(stdout);
}
if (c < 0)
warn("local: %s", local);
if (d < 0) {
if (errno != EPIPE)
warn("netout");
bytes = -1;
}
break;
case TYPE_A:
while ((c = getc(fin)) != EOF) {
if (c == '\n') {
while (hash && (!progress || filesize < 0) &&
(bytes >= hashbytes)) {
(void)putchar('#');
(void)fflush(stdout);
hashbytes += mark;
}
if (ferror(dout))
break;
(void)putc('\r', dout);
bytes++;
}
(void)putc(c, dout);
bytes++;
#if 0 /* this violates RFC */
if (c == '\r') {
(void)putc('\0', dout);
bytes++;
}
#endif
}
if (hash && (!progress || filesize < 0)) {
if (bytes < hashbytes)
(void)putchar('#');
(void)putchar('\n');
(void)fflush(stdout);
}
if (ferror(fin))
warn("local: %s", local);
if (ferror(dout)) {
if (errno != EPIPE)
warn("netout");
bytes = -1;
}
break;
}
progressmeter(1);
if (closefunc != NULL)
(*closefunc)(fin);
(void)fclose(dout);
(void)getreply(0);
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
if (oldintp)
(void)signal(SIGPIPE, oldintp);
if (bytes > 0)
ptransfer(0);
goto cleanupsend;
abort:
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
if (oldintp)
(void)signal(SIGPIPE, oldintp);
if (!cpend) {
code = -1;
return;
}
if (data >= 0) {
(void)close(data);
data = -1;
}
if (dout)
(void)fclose(dout);
(void)getreply(0);
code = -1;
if (closefunc != NULL && fin != NULL)
(*closefunc)(fin);
if (bytes > 0)
ptransfer(0);
cleanupsend:
progress = oprogress;
restart_point = 0;
}
jmp_buf recvabort;
void
abortrecv(notused)
int notused;
{
alarmtimer(0);
mflag = 0;
abrtflag = 0;
puts("\nreceive aborted\nwaiting for remote to finish abort.");
(void)fflush(stdout);
longjmp(recvabort, 1);
}
void
recvrequest(cmd, local, remote, lmode, printnames, ignorespecial)
const char *cmd, *local, *remote, *lmode;
int printnames, ignorespecial;
{
FILE *fout, *din;
int (*closefunc) __P((FILE *));
sig_t oldinti, oldintr, oldintp;
int c, d;
volatile int is_retr, tcrflag, bare_lfs;
static size_t bufsize;
static char *buf;
volatile off_t hashbytes;
struct stat st;
time_t mtime;
struct timeval tval[2];
int oprogress;
int opreserve;
#ifdef __GNUC__ /* XXX: to shut up gcc warnings */
(void)&local;
(void)&fout;
(void)&din;
(void)&closefunc;
(void)&oldinti;
(void)&oldintr;
(void)&oldintp;
#endif
fout = NULL;
din = NULL;
oldinti = NULL;
hashbytes = mark;
direction = "received";
bytes = 0;
bare_lfs = 0;
filesize = -1;
oprogress = progress;
opreserve = preserve;
is_retr = (strcmp(cmd, "RETR") == 0);
if (is_retr && verbose && printnames) {
if (local && (ignorespecial || *local != '-'))
printf("local: %s ", local);
if (remote)
printf("remote: %s\n", remote);
}
if (proxy && is_retr) {
proxtrans(cmd, local, remote);
return;
}
closefunc = NULL;
oldintr = NULL;
oldintp = NULL;
tcrflag = !crflag && is_retr;
if (setjmp(recvabort)) {
while (cpend) {
(void)getreply(0);
}
if (data >= 0) {
(void)close(data);
data = -1;
}
if (oldintr)
(void)signal(SIGINT, oldintr);
if (oldinti)
(void)signal(SIGINFO, oldinti);
progress = oprogress;
preserve = opreserve;
code = -1;
return;
}
oldintr = signal(SIGINT, abortrecv);
oldinti = signal(SIGINFO, psummary);
if (ignorespecial || (strcmp(local, "-") && *local != '|')) {
if (access(local, W_OK) < 0) {
char *dir = strrchr(local, '/');
if (errno != ENOENT && errno != EACCES) {
warn("local: %s", local);
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
code = -1;
return;
}
if (dir != NULL)
*dir = 0;
d = access(dir == local ? "/" : dir ? local : ".", W_OK);
if (dir != NULL)
*dir = '/';
if (d < 0) {
warn("local: %s", local);
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
code = -1;
return;
}
if (!runique && errno == EACCES &&
chmod(local, 0600) < 0) {
warn("local: %s", local);
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
code = -1;
return;
}
if (runique && errno == EACCES &&
(local = gunique(local)) == NULL) {
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
code = -1;
return;
}
}
else if (runique && (local = gunique(local)) == NULL) {
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
code = -1;
return;
}
}
if (!is_retr) {
if (curtype != TYPE_A)
changetype(TYPE_A, 0);
} else {
if (curtype != type)
changetype(type, 0);
filesize = remotesize(remote, 0);
}
if (initconn()) {
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
code = -1;
return;
}
if (setjmp(recvabort))
goto abort;
if (is_retr && restart_point &&
command("REST %qd", (__int64_t) restart_point) != CONTINUE) /* replaced long long for EFI port */
return;
if (remote) {
if (command("%s %s", cmd, remote) != PRELIM) {
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
return;
}
} else {
if (command("%s", cmd) != PRELIM) {
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
return;
}
}
din = dataconn("r");
if (din == NULL)
goto abort;
if (!ignorespecial && strcmp(local, "-") == 0) {
fout = stdout;
progress = 0;
preserve = 0;
} else if (!ignorespecial && *local == '|') {
oldintp = signal(SIGPIPE, SIG_IGN);
fout = popen(local + 1, "w");
if (fout == NULL) {
warn("%s", local+1);
goto abort;
}
progress = 0;
preserve = 0;
closefunc = pclose;
} else {
fout = fopen(local, lmode);
if (fout == NULL) {
warn("local: %s", local);
goto abort;
}
closefunc = fclose;
}
if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
st.st_blksize = BUFSIZ;
if (st.st_blksize > bufsize) {
if (buf)
(void)free(buf);
buf = malloc((unsigned)st.st_blksize);
if (buf == NULL) {
warn("malloc");
bufsize = 0;
goto abort;
}
bufsize = st.st_blksize;
}
if (!S_ISREG(st.st_mode)) {
progress = 0;
preserve = 0;
}
progressmeter(-1);
switch (curtype) {
case TYPE_I:
case TYPE_L:
if (is_retr && restart_point &&
lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
warn("local: %s", local);
progress = oprogress;
preserve = opreserve;
if (closefunc != NULL)
(*closefunc)(fout);
return;
}
errno = d = 0;
while ((c = (int)read(fileno(din), buf, bufsize)) > 0) {
if ((d = (int)write(fileno(fout), buf, c)) != c)
break;
bytes += c;
if (hash && (!progress || filesize < 0)) {
while (bytes >= hashbytes) {
(void)putchar('#');
hashbytes += mark;
}
(void)fflush(stdout);
}
}
if (hash && (!progress || filesize < 0) && bytes > 0) {
if (bytes < mark)
(void)putchar('#');
(void)putchar('\n');
(void)fflush(stdout);
}
if (c < 0) {
if (errno != EPIPE)
warn("netin");
bytes = -1;
}
if (d < c) {
if (d < 0)
warn("local: %s", local);
else
warnx("%s: short write", local);
}
break;
case TYPE_A:
if (is_retr && restart_point) {
int ch;
long i, n;
if (fseek(fout, 0L, SEEK_SET) < 0)
goto done;
n = (long)restart_point;
for (i = 0; i++ < n;) {
if ((ch = getc(fout)) == EOF)
goto done;
if (ch == '\n')
i++;
}
if (fseek(fout, 0L, SEEK_CUR) < 0) {
done:
warn("local: %s", local);
progress = oprogress;
preserve = opreserve;
if (closefunc != NULL)
(*closefunc)(fout);
return;
}
}
while ((c = getc(din)) != EOF) {
if (c == '\n')
bare_lfs++;
while (c == '\r') {
while (hash && (!progress || filesize < 0) &&
(bytes >= hashbytes)) {
(void)putchar('#');
(void)fflush(stdout);
hashbytes += mark;
}
bytes++;
if ((c = getc(din)) != '\n' || tcrflag) {
if (ferror(fout))
goto break2;
(void)putc('\r', fout);
if (c == '\0') {
bytes++;
goto contin2;
}
if (c == EOF)
goto contin2;
}
}
(void)putc(c, fout);
bytes++;
contin2: ;
}
break2:
if (bare_lfs) {
printf(
"WARNING! %d bare linefeeds received in ASCII mode.\n", bare_lfs);
puts("File may not have transferred correctly.");
}
if (hash && (!progress || filesize < 0)) {
if (bytes < hashbytes)
(void)putchar('#');
(void)putchar('\n');
(void)fflush(stdout);
}
if (ferror(din)) {
if (errno != EPIPE)
warn("netin");
bytes = -1;
}
if (ferror(fout))
warn("local: %s", local);
break;
}
progressmeter(1);
progress = oprogress;
preserve = opreserve;
if (closefunc != NULL)
(*closefunc)(fout);
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
if (oldintp)
(void)signal(SIGPIPE, oldintp);
(void)fclose(din);
(void)getreply(0);
if (bytes >= 0 && is_retr) {
if (bytes > 0)
ptransfer(0);
if (preserve && (closefunc == fclose)) {
mtime = remotemodtime(remote, 0);
if (mtime != -1) {
(void)gettimeofday(&tval[0],
(struct timezone *)0);
tval[1].tv_sec = mtime;
tval[1].tv_usec = 0;
if (utimes(local, tval) == -1) {
printf(
"Can't change modification time on %s to %s",
local, asctime(localtime(&mtime)));
}
}
}
}
return;
abort:
/* abort using RFC959 recommended IP,SYNC sequence */
progress = oprogress;
preserve = opreserve;
if (oldintp)
(void)signal(SIGPIPE, oldintp);
(void)signal(SIGINT, SIG_IGN);
if (!cpend) {
code = -1;
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
return;
}
abort_remote(din);
code = -1;
if (data >= 0) {
(void)close(data);
data = -1;
}
if (closefunc != NULL && fout != NULL)
(*closefunc)(fout);
if (din)
(void)fclose(din);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -