X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Ffile_ops.c;h=207a4b19010bb254845a280e3632d22fe7897842;hb=57b37d4ed168b176d594bc149e5d16a1b9f0517a;hp=8fcc068bfd88bf2e1a555c839a6e9de920995603;hpb=f95401b73d6f0c34dd00639be58fa8731e6959e9;p=citadel.git diff --git a/citadel/file_ops.c b/citadel/file_ops.c index 8fcc068bf..207a4b190 100644 --- a/citadel/file_ops.c +++ b/citadel/file_ops.c @@ -1,8 +1,5 @@ /* - * $Id$ - * * Server functions which handle file transfers and room directories. - * */ #include "sysdep.h" @@ -15,6 +12,7 @@ #include #include #include +#include #if TIME_WITH_SYS_TIME # include @@ -34,7 +32,6 @@ #include "config.h" #include "file_ops.h" #include "sysdep_decls.h" -#include "user_ops.h" #include "support.h" #include "room_ops.h" #include "msgbase.h" @@ -46,64 +43,60 @@ #endif #include "ctdl_module.h" +#include "user_ops.h" /* * network_talking_to() -- concurrency checker */ -int network_talking_to(char *nodename, int operation) { +static HashList *nttlist = NULL; +int network_talking_to(const char *nodename, long len, int operation) { - static char *nttlist = NULL; - char *ptr = NULL; - int i; - char buf[SIZ]; int retval = 0; + HashPos *Pos = NULL; + void *vdata; begin_critical_section(S_NTTLIST); switch(operation) { case NTT_ADD: - if (nttlist == NULL) nttlist = strdup(""); - if (nttlist == NULL) break; - nttlist = (char *)realloc(nttlist, - (strlen(nttlist) + strlen(nodename) + 3) ); - strcat(nttlist, "|"); - strcat(nttlist, nodename); + if (nttlist == NULL) + nttlist = NewHash(1, NULL); + Put(nttlist, nodename, len, NewStrBufPlain(nodename, len), HFreeStrBuf); + syslog(LOG_DEBUG, "nttlist: added <%s>\n", nodename); break; - case NTT_REMOVE: - if (nttlist == NULL) break; - if (IsEmptyStr(nttlist)) break; - ptr = malloc(strlen(nttlist)); - if (ptr == NULL) break; - strcpy(ptr, ""); - for (i = 0; i < num_tokens(nttlist, '|'); ++i) { - extract_token(buf, nttlist, i, '|', sizeof buf); - if ( (!IsEmptyStr(buf)) - && (strcasecmp(buf, nodename)) ) { - strcat(ptr, buf); - strcat(ptr, "|"); - } - } - free(nttlist); - nttlist = ptr; + if ((nttlist == NULL) || + (GetCount(nttlist) == 0)) + break; + Pos = GetNewHashPos(nttlist, 1); + if (GetHashPosFromKey (nttlist, nodename, len, Pos)) + DeleteEntryFromHash(nttlist, Pos); + DeleteHashPos(&Pos); + syslog(LOG_DEBUG, "nttlist: removed <%s>\n", nodename); + break; case NTT_CHECK: - if (nttlist == NULL) break; - if (IsEmptyStr(nttlist)) break; - for (i = 0; i < num_tokens(nttlist, '|'); ++i) { - extract_token(buf, nttlist, i, '|', sizeof buf); - if (!strcasecmp(buf, nodename)) ++retval; - } + if ((nttlist == NULL) || + (GetCount(nttlist) == 0)) + break; + if (!GetHash(nttlist, nodename, len, &vdata)) + retval ++; + syslog(LOG_DEBUG, "nttlist: have [%d] <%s>\n", retval, nodename); break; } - if (nttlist != NULL) CtdlLogPrintf(CTDL_DEBUG, "nttlist=<%s>\n", nttlist); end_critical_section(S_NTTLIST); return(retval); } +void cleanup_nttlist(void) +{ + begin_critical_section(S_NTTLIST); + DeleteHash(&nttlist); + end_critical_section(S_NTTLIST); +} @@ -194,7 +187,7 @@ void cmd_movf(char *cmdbuf) return; } - if (getroom(&qrbuf, newroom) != 0) { + if (CtdlGetRoom(&qrbuf, newroom) != 0) { cprintf("%d '%s' does not exist.\n", ERROR + ROOM_NOT_FOUND, newroom); return; } @@ -235,6 +228,7 @@ void OpenCmdResult(char *filename, const char *mime_type) long filesize; fstat(fileno(CC->download_fp), &statbuf); + CC->download_fp_total = statbuf.st_size; filesize = (long) statbuf.st_size; modtime = (time_t) statbuf.st_mtime; @@ -307,6 +301,7 @@ void cmd_oimg(char *cmdbuf) char which_user[USERNAME_SIZE]; int which_floor; int a; + int rv; extract_token(filename, cmdbuf, 0, '|', sizeof filename); @@ -324,7 +319,7 @@ void cmd_oimg(char *cmdbuf) if (!strcasecmp(filename, "_userpic_")) { extract_token(which_user, cmdbuf, 1, '|', sizeof which_user); - if (getuser(&usbuf, which_user) != 0) { + if (CtdlGetUser(&usbuf, which_user) != 0) { cprintf("%d No such user.\n", ERROR + NO_SUCH_USER); return; @@ -363,7 +358,13 @@ void cmd_oimg(char *cmdbuf) ERROR + FILE_NOT_FOUND, pathname, strerror(errno)); return; } - fread(&MimeTestBuf[0], 1, 32, CC->download_fp); + rv = fread(&MimeTestBuf[0], 1, 32, CC->download_fp); + if (rv == -1) { + cprintf("%d Cannot access %s: %s\n", + ERROR + FILE_NOT_FOUND, pathname, strerror(errno)); + return; + } + rewind (CC->download_fp); OpenCmdResult(pathname, GuessMimeType(&MimeTestBuf[0], 32)); } @@ -466,7 +467,7 @@ void cmd_uimg(char *cmdbuf) } } - if (CC->user.axlevel >= 6) { + if (CC->user.axlevel >= AxAideU) { snprintf(CC->upl_path, sizeof CC->upl_path, "%s/%s", ctdl_image_dir, @@ -481,7 +482,7 @@ void cmd_uimg(char *cmdbuf) } if ((!strcasecmp(basenm, "_floorpic_")) - && (CC->user.axlevel >= 6)) { + && (CC->user.axlevel >= AxAideU)) { which_floor = extract_int(cmdbuf, 2); snprintf(CC->upl_path, sizeof CC->upl_path, "%s/floor.%d.gif", @@ -547,7 +548,7 @@ void cmd_clos(char *cmdbuf) /* * abort an upload */ -void abort_upl(struct CitContext *who) +void abort_upl(CitContext *who) { if (who->upload_fp != NULL) { fclose(who->upload_fp); @@ -565,6 +566,7 @@ void cmd_ucls(char *cmd) { FILE *fp; char upload_notice[512]; + static int seq = 0; if (CC->upload_fp == NULL) { cprintf("%d You don't have an upload file open.\n", ERROR + RESOURCE_NOT_OPEN); @@ -575,11 +577,31 @@ void cmd_ucls(char *cmd) CC->upload_fp = NULL; if ((!strcasecmp(cmd, "1")) && (CC->upload_type != UPL_FILE)) { - CC->upload_type = UPL_FILE; cprintf("%d Upload completed.\n", CIT_OK); - /* FIXME ... here we need to trigger a network run */ + if (CC->upload_type == UPL_NET) { + char final_filename[PATH_MAX]; + snprintf(final_filename, sizeof final_filename, + "%s/%s.%04lx.%04x", + ctdl_netin_dir, + CC->net_node, + (long)getpid(), + ++seq + ); + + if (link(CC->upl_path, final_filename) == 0) { + unlink(CC->upl_path); + } + else { + syslog(LOG_ALERT, "Cannot link %s to %s: %s\n", + CC->upl_path, final_filename, strerror(errno) + ); + } + + /* FIXME ... here we need to trigger a network run */ + } + CC->upload_type = UPL_FILE; return; } @@ -611,7 +633,6 @@ void cmd_ucls(char *cmd) } - /* * read from the download file */ @@ -619,9 +640,9 @@ void cmd_read(char *cmdbuf) { long start_pos; size_t bytes; - size_t actual_bytes; - char *buf = NULL; + char buf[SIZ]; + /* The client will transmit its requested offset and byte count */ start_pos = extract_long(cmdbuf, 0); bytes = extract_int(cmdbuf, 1); @@ -631,18 +652,24 @@ void cmd_read(char *cmdbuf) return; } - if (bytes > 100000) bytes = 100000; - buf = malloc(bytes + 1); + /* If necessary, reduce the byte count to the size of our buffer */ + if (bytes > sizeof(buf)) { + bytes = sizeof(buf); + } fseek(CC->download_fp, start_pos, 0); - actual_bytes = fread(buf, 1, bytes, CC->download_fp); - cprintf("%d %d\n", BINARY_FOLLOWS, (int)actual_bytes); - client_write(buf, actual_bytes); - free(buf); + bytes = fread(buf, 1, bytes, CC->download_fp); + if (bytes > 0) { + /* Tell the client the actual byte count and transmit it */ + cprintf("%d %d\n", BINARY_FOLLOWS, (int)bytes); + client_write(buf, bytes); + } + else { + cprintf("%d %s\n", ERROR, strerror(errno)); + } } - /* * write to the upload file */ @@ -650,6 +677,7 @@ void cmd_writ(char *cmdbuf) { int bytes; char *buf; + int rv; unbuffer_output(); @@ -669,7 +697,11 @@ void cmd_writ(char *cmdbuf) cprintf("%d %d\n", SEND_BINARY, bytes); buf = malloc(bytes + 1); client_read(buf, bytes); - fwrite(buf, bytes, 1, CC->upload_fp); + rv = fwrite(buf, bytes, 1, CC->upload_fp); + if (rv == -1) { + syslog(LOG_EMERG, "Couldn't write: %s\n", + strerror(errno)); + } free(buf); } @@ -723,6 +755,7 @@ void cmd_ndop(char *cmdbuf) CC->dl_is_net = 1; stat(pathname, &statbuf); + CC->download_fp_total = statbuf.st_size; cprintf("%d %ld\n", CIT_OK, (long)statbuf.st_size); } @@ -747,7 +780,7 @@ void cmd_nuop(char *cmdbuf) snprintf(CC->upl_path, sizeof CC->upl_path, "%s/%s.%04lx.%04x", - ctdl_netin_dir, + ctdl_nettmp_dir, CC->net_node, (long)getpid(), ++seq); @@ -779,18 +812,21 @@ void cmd_nuop(char *cmdbuf) CTDL_MODULE_INIT(file_ops) { - CtdlRegisterProtoHook(cmd_delf, "DELF", "Autoconverted. TODO: document me."); - CtdlRegisterProtoHook(cmd_movf, "MOVF", "Autoconverted. TODO: document me."); - CtdlRegisterProtoHook(cmd_open, "OPEN", "Autoconverted. TODO: document me."); - CtdlRegisterProtoHook(cmd_clos, "CLOS", "Autoconverted. TODO: document me."); - CtdlRegisterProtoHook(cmd_uopn, "UOPN", "Autoconverted. TODO: document me."); - CtdlRegisterProtoHook(cmd_ucls, "UCLS", "Autoconverted. TODO: document me."); - CtdlRegisterProtoHook(cmd_read, "READ", "Autoconverted. TODO: document me."); - CtdlRegisterProtoHook(cmd_writ, "WRIT", "Autoconverted. TODO: document me."); - CtdlRegisterProtoHook(cmd_oimg, "OIMG", "Autoconverted. TODO: document me."); - CtdlRegisterProtoHook(cmd_ndop, "NDOP", "Autoconverted. TODO: document me."); - CtdlRegisterProtoHook(cmd_nuop, "NUOP", "Autoconverted. TODO: document me."); - CtdlRegisterProtoHook(cmd_uimg, "UIMG", "Autoconverted. TODO: document me."); + if (!threading) { + CtdlRegisterProtoHook(cmd_delf, "DELF", "Delete a file"); + CtdlRegisterProtoHook(cmd_movf, "MOVF", "Move a file"); + CtdlRegisterProtoHook(cmd_open, "OPEN", "Open a download file transfer"); + CtdlRegisterProtoHook(cmd_clos, "CLOS", "Close a download file transfer"); + CtdlRegisterProtoHook(cmd_uopn, "UOPN", "Open an upload file transfer"); + CtdlRegisterProtoHook(cmd_ucls, "UCLS", "Close an upload file transfer"); + CtdlRegisterProtoHook(cmd_read, "READ", "File transfer read operation"); + CtdlRegisterProtoHook(cmd_writ, "WRIT", "File transfer write operation"); + CtdlRegisterProtoHook(cmd_ndop, "NDOP", "Open a network spool file for download"); + CtdlRegisterProtoHook(cmd_nuop, "NUOP", "Open a network spool file for upload"); + CtdlRegisterProtoHook(cmd_oimg, "OIMG", "Open an image file for download"); + CtdlRegisterProtoHook(cmd_uimg, "UIMG", "Upload an image file"); + CtdlRegisterCleanupHook(cleanup_nttlist); + } /* return our Subversion id for the Log */ - return "$Id$"; + return "file_ops"; }