/* file.c * * This file is part of ftp. * * * 01/25/96 Initial Release Michael Temari, */ #include #include #include #include #include #include #include #include #include "ftp.h" #include "file.h" #include "net.h" _PROTOTYPE(static char *dir, (char *path, int full)); _PROTOTYPE(static int asciisend, (int fd, int fdout)); _PROTOTYPE(static int binarysend, (int fd, int fdout)); _PROTOTYPE(static int asciirecv, (int fd, int fdin)); _PROTOTYPE(static int binaryrecv, (int fd, int fdin)); _PROTOTYPE(static int asciisize, (int fd, off_t *filesize)); _PROTOTYPE(static off_t asciisetsize, (int fd, off_t filesize)); static char buffer[512 << sizeof(char *)]; static char bufout[512 << sizeof(char *)]; static char line2[512]; static char *dir(path, full) char *path; int full; { char cmd[128]; static char name[32]; tmpnam(name); if(full) sprintf(cmd, "ls -l %s > %s", path, name); else sprintf(cmd, "ls %s > %s", path, name); system(cmd); return(name); } static int asciisend(fd, fdout) int fd; int fdout; { int s, len; char c; char *p; char *op, *ope; unsigned long total=0L; if(atty) { printf("Sent "); fflush(stdout); } op = bufout; ope = bufout + sizeof(bufout) - 3; while((s = read(fd, buffer, sizeof(buffer))) > 0) { total += (long)s; p = buffer; while(s-- > 0) { c = *p++; if(c == '\r') { *op++ = '\r'; total++; } *op++ = c; if(op >= ope) { write(fdout, bufout, op - bufout); op = bufout; } } if(atty) { printf("%9lu bytes\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", total); fflush(stdout); } } if(op > bufout) write(fdout, bufout, op - bufout); if(atty) { printf("\n"); fflush(stdout); } return(s); } static int binarysend(fd, fdout) int fd; int fdout; { int s; unsigned long total=0L; if(atty) { printf("Sent "); fflush(stdout); } while((s = read(fd, buffer, sizeof(buffer))) > 0) { write(fdout, buffer, s); total += (long)s; if(atty) { printf("%9lu bytes\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", total); fflush(stdout); } } if(atty) { printf("\n"); fflush(stdout); } return(s); } int sendfile(fd, fdout) int fd; int fdout; { int s; switch(type) { case TYPE_A: s = asciisend(fd, fdout); break; default: s = binarysend(fd, fdout); } if(s < 0) return(-1); else return(0); } static int asciirecv(fd, fdin) int fd; int fdin; { int s, len; int gotcr; char c; char *p; char *op, *ope; unsigned long total=0L; if(isatty && fd > 2) { printf("Received "); fflush(stdout); } gotcr = 0; op = bufout; ope = bufout + sizeof(bufout) - 3; while((s = read(fdin, buffer, sizeof(buffer))) > 0) { p = buffer; total += (long)s; while(s-- > 0) { c = *p++; if(gotcr) { gotcr = 0; if(c != '\n') *op++ = '\r'; } if(c == '\r') gotcr = 1; else *op++ = c; if(op >= ope) { write(fd, bufout, op - bufout); op = bufout; } } if(atty && fd > 2) { printf("%9lu bytes\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", total); fflush(stdout); } } if(gotcr) *op++ = '\r'; if(op > bufout) write(fd, bufout, op - bufout); if(atty && fd > 2) { printf("\n"); fflush(stdout); } return(s); } static binaryrecv(fd, fdin) int fd; int fdin; { int s; unsigned long total=0L; if(atty && fd > 2) { printf("Received "); fflush(stdout); } while((s = read(fdin, buffer, sizeof(buffer))) > 0) { write(fd, buffer, s); total += (long)s; if(atty && fd > 2) { printf("%9lu bytes\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", total); fflush(stdout); } } if(atty && fd > 2) { printf("\n"); fflush(stdout); } return(s); } int recvfile(fd, fdin) int fd; int fdin; { int s; switch(type) { case TYPE_A: s = asciirecv(fd, fdin); break; default: s = binaryrecv(fd, fdin); } if(s < 0) return(-1); else return(0); } int DOascii() { int s; if(DOcmdcheck()) return(0); s = DOcommand("TYPE", "A"); type = TYPE_A; return(s); } int DObinary() { int s; if(DOcmdcheck()) return(0); s = DOcommand("TYPE", "I"); type = TYPE_I; return(s); } int DOpwd() { int s; if(DOcmdcheck()) return(0); s = DOcommand("PWD", ""); if(s == 500 || s == 502) s = DOcommand("XPWD", ""); return(s); } int DOcd() { char *path; int s; if(DOcmdcheck()) return(0); path = cmdargv[1]; if(cmdargc < 2) { readline("Path: ", line2, sizeof(line2)); path = line2; } if(!strcmp(path, "..")) s = DOcommand("CDUP", ""); else s = DOcommand("CWD", path); if(s == 500 || s == 502) { if(!strcmp(path, "..")) s = DOcommand("XCUP", ""); else s = DOcommand("XCWD", path); } return(s); } int DOmkdir() { char *path; int s; if(DOcmdcheck()) return(0); path = cmdargv[1]; if(cmdargc < 2) { readline("Directory: ", line2, sizeof(line2)); path = line2; } s = DOcommand("MKD", path); if(s == 500 || s == 502) s = DOcommand("XMKD", path); return(s); } int DOrmdir() { char *path; int s; if(DOcmdcheck()) return(0); path = cmdargv[1]; if(cmdargc < 2) { readline("Directory: ", line2, sizeof(line2)); path = line2; } s = DOcommand("RMD", path); if(s == 500 || s == 502) s = DOcommand("XRMD", path); return(s); } int DOdelete() { char *file; if(DOcmdcheck()) return(0); file = cmdargv[1]; if(cmdargc < 2) { readline("File: ", line2, sizeof(line2)); file = line2; } return(DOcommand("DELE", file)); } int DOmdtm() { char *file; if(DOcmdcheck()) return(0); file = cmdargv[1]; if(cmdargc < 2) { readline("File: ", line2, sizeof(line2)); file = line2; } return(DOcommand("MDTM", file)); } int DOsize() { char *file; if(DOcmdcheck()) return(0); file = cmdargv[1]; if(cmdargc < 2) { readline("File: ", line2, sizeof(line2)); file = line2; } return(DOcommand("SIZE", file)); } int DOstat() { char *file; if(cmdargc < 2) if(!linkopen) { printf("You must \"OPEN\" a connection first.\n"); return(0); } else return(DOcommand("STAT", "")); if(DOcmdcheck()) return(0); file = cmdargv[1]; if(cmdargc < 2) { readline("File: ", line2, sizeof(line2)); file = line2; } return(DOcommand("STAT", file)); } int DOlist() { char *path; char *local; int fd; int s; if(DOcmdcheck()) return(0); path = cmdargv[1]; if(cmdargc < 2) path = ""; if(cmdargc < 3) local = ""; else local = cmdargv[2]; if(*local == '\0') fd = 1; else fd = open(local, O_WRONLY | O_CREAT | O_TRUNC, 0666); if(fd < 0) { printf("Could not open local file %s. Error %s\n", local, strerror(errno)); return(0); } s = DOdata("LIST", path, RETR, fd); if(fd > 2) close(fd); return(s); } int DOnlst() { char *path; char *local; int fd; int s; if(DOcmdcheck()) return(0); path = cmdargv[1]; if(cmdargc < 2) path = ""; if(cmdargc < 3) local = ""; else local = cmdargv[2]; if(*local == '\0') fd = 1; else fd = open(local, O_WRONLY | O_CREAT | O_TRUNC, 0666); if(fd < 0) { printf("Could not open local file %s. Error %s\n", local, strerror(errno)); return(0); } s = DOdata("NLST", path, RETR, fd); if(fd > 2) close(fd); return(s); } int DOretr() { char *file, *localfile; int fd; int s; if(DOcmdcheck()) return(0); file = cmdargv[1]; if(cmdargc < 2) { readline("Remote File: ", line2, sizeof(line2)); file = line2; } if(cmdargc < 3) localfile = file; else localfile = cmdargv[2]; fd = open(localfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); if(fd < 0) { printf("Could not open local file %s. Error %s\n", localfile, strerror(errno)); return(0); } s = DOdata("RETR", file, RETR, fd); close(fd); return(s); } int DOrretr() { char *file, *localfile; int fd; int s; off_t filesize; char restart[16]; if(DOcmdcheck()) return(0); file = cmdargv[1]; if(cmdargc < 2) { readline("Remote File: ", line2, sizeof(line2)); file = line2; } if(cmdargc < 3) localfile = file; else localfile = cmdargv[2]; fd = open(localfile, O_RDWR); if(fd < 0) { printf("Could not open local file %s. Error %s\n", localfile, strerror(errno)); return(0); } if(type == TYPE_A) { if(asciisize(fd, &filesize)) { printf("Could not determine ascii file size of %s\n", localfile); close(fd); return(0); } } else filesize = lseek(fd, 0, SEEK_END); sprintf(restart, "%lu", filesize); s = DOcommand("REST", restart); if(s != 350) { close(fd); return(s); } s = DOdata("RETR", file, RETR, fd); close(fd); return(s); } int DOMretr() { char *files; int fd, s; FILE *fp; char name[32]; if(DOcmdcheck()) return(0); files = cmdargv[1]; if(cmdargc < 2) { readline("Files: ", line2, sizeof(line2)); files = line2; } tmpnam(name); fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666); if(fd < 0) { printf("Could not open local file %s. Error %s\n", name, strerror(errno)); return(0); } s = DOdata("NLST", files, RETR, fd); close(fd); if(s == 226) { fp = fopen(name, "r"); unlink(name); if(fp == (FILE *)NULL) { printf("Unable to open file listing.\n"); return(0); } while(fgets(line2, sizeof(line2), fp) != (char *)NULL) { line2[strlen(line2)-1] = '\0'; printf("Retrieving file: %s\n", line2); fflush(stdout); fd = open(line2, O_WRONLY | O_CREAT | O_TRUNC, 0666); if(fd < 0) printf("Unable to open local file %s\n", line2); else { s = DOdata("RETR", line2, RETR, fd); close(fd); if(s < 0) break; } } fclose(fp); } else unlink(name); return(s); } int DOappe() { char *file, *remotefile; int fd; int s; if(DOcmdcheck()) return(0); file = cmdargv[1]; if(cmdargc < 2) { readline("Local File: ", line2, sizeof(line2)); file = line2; } if(cmdargc < 3) remotefile = file; else remotefile = cmdargv[2]; fd = open(file, O_RDONLY); if(fd < 0) { printf("Could not open local file %s. Error %s\n", file, strerror(errno)); return(0); } s = DOdata("APPE", remotefile, STOR, fd); close(fd); return(s); } int DOstor() { char *file, *remotefile; int fd; int s; if(DOcmdcheck()) return(0); file = cmdargv[1]; if(cmdargc < 2) { readline("Local File: ", line2, sizeof(line2)); file = line2; } if(cmdargc < 3) remotefile = file; else remotefile = cmdargv[2]; fd = open(file, O_RDONLY); if(fd < 0) { printf("Could not open local file %s. Error %s\n", file, strerror(errno)); return(0); } s = DOdata("STOR", remotefile, STOR, fd); close(fd); return(s); } int DOrstor() { char *file, *remotefile; int fd; int s; off_t filesize, rmtsize; char restart[16]; if(DOcmdcheck()) return(0); file = cmdargv[1]; if(cmdargc < 2) { readline("Local File: ", line2, sizeof(line2)); file = line2; } if(cmdargc < 3) remotefile = file; else remotefile = cmdargv[2]; s = DOcommand("SIZE", remotefile); if(s != 215) return(s); rmtsize = atol(reply+4); fd = open(file, O_RDONLY); if(fd < 0) { printf("Could not open local file %s. Error %s\n", file, strerror(errno)); return(0); } if(type == TYPE_A) filesize = asciisetsize(fd, rmtsize); else filesize = lseek(fd, rmtsize, SEEK_SET); if(filesize != rmtsize) { printf("Could not set file start of %s\n", file); close(fd); return(0); } sprintf(restart, "%lu", rmtsize); s = DOcommand("REST", restart); if(s != 350) { close(fd); return(s); } s = DOdata("STOR", remotefile, STOR, fd); close(fd); return(s); } int DOstou() { char *file, *remotefile; int fd; int s; if(DOcmdcheck()) return(0); file = cmdargv[1]; if(cmdargc < 2) { readline("Local File: ", line2, sizeof(line2)); file = line2; } if(cmdargc < 3) remotefile = file; else remotefile = cmdargv[2]; fd = open(file, O_RDONLY); if(fd < 0) { printf("Could not open local file %s. Error %s\n", file, strerror(errno)); return(0); } s = DOdata("STOU", remotefile, STOR, fd); close(fd); return(s); } int DOMstor() { char *files; char *name; int fd, s; FILE *fp; if(DOcmdcheck()) return(0); files = cmdargv[1]; if(cmdargc < 2) { readline("Files: ", line2, sizeof(line2)); files = line2; } name = dir(files, 0); fp = fopen(name, "r"); if(fp == (FILE *)NULL) { printf("Unable to open listing file.\n"); return(0); } while(fgets(line2, sizeof(line2), fp) != (char *)NULL) { line2[strlen(line2)-1] = '\0'; printf("Sending file: %s\n", line2); fflush(stdout); fd = open(line2, O_RDONLY); if(fd < 0) printf("Unable to open local file %s\n", line2); else { s = DOdata("STOR", line2, STOR, fd); close(fd); if(s < 0) break; } } fclose(fp); unlink(name); return(s); } static int asciisize(fd, filesize) int fd; off_t *filesize; { unsigned long count; char *p, *pp; int cnt; count = 0; while((cnt = read(fd, buffer, sizeof(buffer))) > 0) { p = buffer; pp = buffer + cnt; count += cnt; while(p < pp) if(*p++ == '\n') count++; } if(cnt == 0) { *filesize = count; return(0); } return(1); } static off_t asciisetsize(fd, filesize) int fd; off_t filesize; { off_t sp; int s; sp = 0; while(sp < filesize) { s = read(fd, buffer, 1); if(s < 0) return(-1); if(s == 0) break; sp++; if(*buffer == '\n') sp++; } return(sp); }