📄 filetransfer.c++
字号:
if (isspace(*cp) || !isgraph(*cp)) { reply(553, "Bad filename; includes invalid character."); return; } mode_t omask = umask(027); FILE* fout = fopen(name, restart_point ? "r+w" : mode); if (fout != NULL) { setFileOwner(name); if (restart_point && lseek(fileno(fout), restart_point, SEEK_SET) != restart_point) perror_reply(550, name, errno); else { time_t start_time = Sys::now(); int code; FILE* din = openDataConn("r", code); if (din != NULL) { reply(code, "%s for %s.", dataConnMsg(code), name); file_size = -1; if (recvData(din, fout)) reply(226, "Transfer complete."); if (TRACE(INXFERS) && xferfaxlog != -1) logTransfer("i", *sd, name, start_time); closeDataConn(din); } } fclose(fout); } else perror_reply(553, name, errno); (void) umask(omask); }}/* * STOU (STOre Unique) file. * STOT (STOre unique Temporary) file. * * STOT differs from STOU in that files created with STOT * are automatically unlinked when the process terminates * while files created with STOU are not. STOT is intended * for clients creating documents that are to be sent and * then expunged. STOU is for documents that are intended * be shared across multiple sessions. */voidHylaFAXServer::storeUniqueCmd(bool isTemp){ fxStr emsg; u_int seqnum = getDocumentNumber(emsg); if (seqnum != (u_int) -1) { fxStr filename = fxStr::format("/%s/doc%u.%s" , isTemp ? FAX_TMPDIR : FAX_DOCDIR , seqnum , formats[form].suffix ); FILE* fout = fopen(filename, "w"); if (fout != NULL) { setFileOwner(filename); FileCache::chmod(filename, 0640); // sync cache if (isTemp) tempFiles.append(filename); time_t start_time = Sys::now(); int code; FILE* din = openDataConn("r", code); if (din != NULL) { reply(code, "FILE: %s (%s).", (const char*) filename, dataConnMsg(code)); file_size = -1; if (recvData(din, fout)) reply(226, "Transfer complete (FILE: %s).", (const char*) filename); if (TRACE(INXFERS) && xferfaxlog != -1) logTransfer("i" , *dirLookup(isTemp ? "/" FAX_TMPDIR : "/" FAX_DOCDIR) , filename , start_time ); closeDataConn(din); } fclose(fout); } else perror_reply(553, filename, errno); } else reply(553, "%s", (const char*)emsg);}/* * Tranfer the contents of "fdin" to "fdout". */boolHylaFAXServer::sendData(FILE* fdin, FILE* fdout){ state |= S_TRANSFER; if (setjmp(urgcatch) != 0) { state &= ~S_TRANSFER; return (false); }#define PACK(a,b) (((a)<<8)|(b)) switch (PACK(type,mode)) { case PACK(TYPE_I,MODE_S): case PACK(TYPE_L,MODE_S): if (sendIData(fileno(fdin), fileno(fdout))) { state &= ~S_TRANSFER; return (true); } break; case PACK(TYPE_I,MODE_Z): case PACK(TYPE_L,MODE_Z): if (sendZData(fileno(fdin), fileno(fdout))) { state &= ~S_TRANSFER; return (true); } break; case PACK(TYPE_A,MODE_S): for (;;) { int c = getc(fdin); if (c == EOF) { fflush(fdout); if (ferror(fdout)) { perror_reply(426, "Data Connection", errno); break; } if (ferror(fdin)) { perror_reply(551, "Error on input file", errno); break; } state &= ~S_TRANSFER; return (true); } byte_count++; if (c == '\n') { // \n -> \r\n if (ferror(fdout)) { // check at the end of each line perror_reply(426, "Data connection", errno); break; } putc('\r', fdout); } putc(c, fdout); } break; default: reply(550, "TYPE %s, MODE %s not implemented." , typenames[type] , modenames[mode] ); break; }#undef PACK state &= ~S_TRANSFER; return (false);}boolHylaFAXServer::sendIData(int fdin, int fdout){ char buf[16*1024]; for (;;) { int cc = read(fdin, buf, sizeof (buf)); if (cc == 0) return (true); if (cc < 0) { perror_reply(551, "Error reading input file", errno); break; } if (write(fdout, buf, cc) != cc) { perror_reply(426, "Data connection", errno); break; } byte_count += cc; } return (false);}boolHylaFAXServer::sendZData(int fdin, int fdout){ z_stream zstream; zstream.zalloc = NULL; zstream.zfree = NULL; zstream.opaque = NULL; zstream.data_type = Z_BINARY; if (deflateInit(&zstream, Z_DEFAULT_COMPRESSION) == Z_OK) { char obuf[16*1024]; zstream.next_out = (Bytef*) obuf; zstream.avail_out = sizeof (obuf); int cc; for (;;) { char buf[16*1024]; cc = read(fdin, buf, sizeof (buf)); if (cc == 0) break; if (cc < 0) { perror_reply(551, "Error reading input file", errno); goto bad; } zstream.next_in = (Bytef*) buf; zstream.avail_in = cc; do { if (deflate(&zstream, Z_NO_FLUSH) != Z_OK) { reply(452, "Compressor error: %s", zstream.msg); goto bad; } if (zstream.avail_out == 0) { if (write(fdout, obuf, sizeof (obuf)) != sizeof (obuf)) { perror_reply(426, "Data connection", errno); goto bad; } byte_count += sizeof (obuf); zstream.next_out = (Bytef*) obuf; zstream.avail_out = sizeof (obuf); } } while (zstream.avail_in > 0); } int state; do { switch (state = deflate(&zstream, Z_FINISH)) { case Z_STREAM_END: case Z_OK: if (zstream.avail_out != sizeof (obuf)) { cc = sizeof (obuf) - zstream.avail_out; if (write(fdout, obuf, cc) != cc) { perror_reply(426, "Data connection", errno); goto bad; } byte_count += cc; zstream.next_out = (Bytef*) obuf; zstream.avail_out = sizeof (obuf); } break; default: reply(426, "Compressor error: %s", zstream.msg); goto bad; } } while (state != Z_STREAM_END); deflateEnd(&zstream); return (true);bad: deflateEnd(&zstream); } else reply(452, "Can not initialize compression library: %s", zstream.msg); return (false);}/* * Transfer data from peer to file. */boolHylaFAXServer::recvData(FILE* fdin, FILE* fdout){ state |= S_TRANSFER; if (setjmp(urgcatch) != 0) { state &= ~S_TRANSFER; return (false); }#define PACK(a,b) (((a)<<8)|(b)) switch (PACK(type,mode)) { case PACK(TYPE_I,MODE_S): case PACK(TYPE_L,MODE_S): if (recvIData(fileno(fdin), fileno(fdout))) { state &= ~S_TRANSFER; return (true); } break; case PACK(TYPE_I,MODE_Z): case PACK(TYPE_L,MODE_Z): if (recvZData(fileno(fdin), fileno(fdout))) { state &= ~S_TRANSFER; return (true); } break; case PACK(TYPE_A,MODE_S): for (;;) { int c = getc(fdin); if (c == EOF) { fflush(fdout); if (ferror(fdin)) { perror_reply(426, "Data Connection", errno); break; } if (ferror(fdout)) { perror_reply(452, "Error writing output file", errno); break; } state &= ~S_TRANSFER; return (true); } byte_count++; if (c == '\r') { // \r\n -> \n if (ferror(fdout)) { // check at the end of each line perror_reply(452, "Error writing output file", errno); break; } c = getc(fdin); if (c != '\n') { putc('\r', fdout); if (c == EOF) continue; } byte_count++; } putc(c, fdout); } break; default: reply(550, "TYPE %s, MODE %s not implemented." , typenames[type] , modenames[mode] ); break; }#undef PACK state &= ~S_TRANSFER; return (false);}boolHylaFAXServer::recvIData(int fdin, int fdout){ char buf[16*1024]; // XXX better if page-aligned for (;;) { int cc = read(fdin, buf, sizeof (buf)); if (cc == 0) return (true); if (cc < 0) { perror_reply(426, "Data Connection", errno); break; } if (write(fdout, buf, cc) != cc) { perror_reply(452, "Error writing output file", errno); break; } byte_count += cc; } return (false);}boolHylaFAXServer::recvZData(int fdin, int fdout){ z_stream zstream; zstream.zalloc = NULL; zstream.zfree = NULL; zstream.opaque = NULL; zstream.data_type = Z_BINARY; if (inflateInit(&zstream) == Z_OK) { char obuf[16*1024]; zstream.next_out = (Bytef*) obuf; zstream.avail_out = sizeof (obuf); for (;;) { char buf[16*1024]; int cc = read(fdin, buf, sizeof (buf)); if (cc == 0) { size_t occ = sizeof (obuf) - zstream.avail_out; if (occ > 0 && write(fdout, obuf, occ) != (ssize_t)occ) { perror_reply(452, "Error writing output file", errno); break; } (void) inflateEnd(&zstream); return (true); } if (cc < 0) { perror_reply(426, "Data Connection", errno); break; } byte_count += cc; zstream.next_in = (Bytef*) buf; zstream.avail_in = cc; do { int state = inflate(&zstream, Z_PARTIAL_FLUSH); if (state == Z_STREAM_END) break; if (state != Z_OK) { reply(452, "Decoding error: %s", zstream.msg); goto bad; } size_t occ = sizeof (obuf) - zstream.avail_out; if (write(fdout, obuf, occ) != (ssize_t)occ) { perror_reply(452, "Error writing output file", errno); goto bad; } zstream.next_out = (Bytef*) obuf; zstream.avail_out = sizeof (obuf); } while (zstream.avail_in > 0); }bad: (void) inflateEnd(&zstream); } else reply(452, "Can not initialize decoder: %s", zstream.msg); return (false);}voidHylaFAXServer::formHelpCmd(void){ lreply(211, "Supported file formats:"); for (u_int i = 0, n = N(formats); i < n; i++) lreply(211, "%8s%s %s" , formats[i].name , formats[i].supported ? " " : "*" , formats[i].help ); reply(211, "Formats marked with a * are not supported.");}voidHylaFAXServer::formCmd(const char* name){ fxStr f(name); f.raisecase(); for (u_int i = 0, n = N(formats); i < n; i++) if (f == formats[i].name) { if (formats[i].supported) { form = i; reply(200, "Format set to %s.", (const char*) f); } else reply(504, "Format %s not supported.", (const char*) f); return; } reply(504, "Unknown format %s.", name);}#undef NvoidHylaFAXServer::typeCmd(const char* name){ if (strcasecmp(name, "I") == 0) type = TYPE_I; else if (strcasecmp(name, "A") == 0) type = TYPE_A; else if (strcasecmp(name, "L") == 0) type = TYPE_L; else { reply(504, "Type %s not supported.", name); return; } reply(200, "Type set to %s.", typenames[type]);}voidHylaFAXServer::modeCmd(const char* name){ if (strcasecmp(name, "S") == 0) mode = MODE_S; else if (strcasecmp(name, "Z") == 0) mode = MODE_Z; else { reply(504, "Mode %s not supported.", name); return; } reply(200, "Mode set to %s.", modenames[mode]);}voidHylaFAXServer::struCmd(const char* name){ if (strcasecmp(name, "F") == 0) stru = STRU_F; else if (strcasecmp(name, "T") == 0) stru = STRU_T; else { reply(504, "Structure %s not supported.", name); return; } reply(200, "Structure set to %s.", strunames[stru]);}voidHylaFAXServer::printTransferStatus(FILE* fd){ if (restart_point) fprintf(fd, " Data transfer restart pending at %lu\r\n", (u_long) restart_point); fprintf(fd, " TYPE: %s", typenames[type]); if (type == TYPE_L) fprintf(fd, " %d", CHAR_BIT); fprintf(fd, "; STRU: %s; MODE: %s; FORM: %s\r\n" , strunames[stru] , modenames[mode] , formats[form].name );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -