Back to index

citadel  8.12
file_ops.c
Go to the documentation of this file.
00001 /* 
00002  * Server functions which handle file transfers and room directories.
00003  */
00004 
00005 #include "sysdep.h"
00006 #include <stdlib.h>
00007 #include <unistd.h>
00008 #include <stdio.h>
00009 #include <fcntl.h>
00010 #include <sys/stat.h>
00011 #include <errno.h>
00012 #include <ctype.h>
00013 #include <string.h>
00014 #include <sys/stat.h>
00015 #include <sys/mman.h>
00016 
00017 #if TIME_WITH_SYS_TIME
00018 # include <sys/time.h>
00019 # include <time.h>
00020 #else
00021 # if HAVE_SYS_TIME_H
00022 #  include <sys/time.h>
00023 # else
00024 #  include <time.h>
00025 # endif
00026 #endif
00027 
00028 #include <limits.h>
00029 #include <libcitadel.h>
00030 #include "citadel.h"
00031 #include "server.h"
00032 #include "config.h"
00033 #include "file_ops.h"
00034 #include "sysdep_decls.h"
00035 #include "support.h"
00036 #include "room_ops.h"
00037 #include "msgbase.h"
00038 #include "citserver.h"
00039 #include "threads.h"
00040 
00041 #ifndef HAVE_SNPRINTF
00042 #include "snprintf.h"
00043 #endif
00044 
00045 #include "ctdl_module.h"
00046 #include "user_ops.h"
00047 
00048 
00049 
00050 /*
00051  * Server command to delete a file from a room's directory
00052  */
00053 void cmd_delf(char *filename)
00054 {
00055        char pathname[64];
00056        int a;
00057 
00058        if (CtdlAccessCheck(ac_room_aide))
00059               return;
00060 
00061        if ((CC->room.QRflags & QR_DIRECTORY) == 0) {
00062               cprintf("%d No directory in this room.\n",
00063                      ERROR + NOT_HERE);
00064               return;
00065        }
00066 
00067        if (IsEmptyStr(filename)) {
00068               cprintf("%d You must specify a file name.\n",
00069                      ERROR + FILE_NOT_FOUND);
00070               return;
00071        }
00072        for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
00073               if ( (filename[a] == '/') || (filename[a] == '\\') ) {
00074                      filename[a] = '_';
00075               }
00076        }
00077        snprintf(pathname, sizeof pathname,
00078                       "%s/%s/%s",
00079                       ctdl_file_dir,
00080                       CC->room.QRdirname, filename);
00081        a = unlink(pathname);
00082        if (a == 0) {
00083               cprintf("%d File '%s' deleted.\n", CIT_OK, pathname);
00084        }
00085        else {
00086               cprintf("%d File '%s' not found.\n",
00087                      ERROR + FILE_NOT_FOUND, pathname);
00088        }
00089 }
00090 
00091 
00092 
00093 
00094 /*
00095  * move a file from one room directory to another
00096  */
00097 void cmd_movf(char *cmdbuf)
00098 {
00099        char filename[PATH_MAX];
00100        char pathname[PATH_MAX];
00101        char newpath[PATH_MAX];
00102        char newroom[ROOMNAMELEN];
00103        char buf[PATH_MAX];
00104        int a;
00105        struct ctdlroom qrbuf;
00106 
00107        extract_token(filename, cmdbuf, 0, '|', sizeof filename);
00108        extract_token(newroom, cmdbuf, 1, '|', sizeof newroom);
00109 
00110        if (CtdlAccessCheck(ac_room_aide)) return;
00111 
00112        if ((CC->room.QRflags & QR_DIRECTORY) == 0) {
00113               cprintf("%d No directory in this room.\n",
00114                      ERROR + NOT_HERE);
00115               return;
00116        }
00117 
00118        if (IsEmptyStr(filename)) {
00119               cprintf("%d You must specify a file name.\n",
00120                      ERROR + FILE_NOT_FOUND);
00121               return;
00122        }
00123 
00124        for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
00125               if ( (filename[a] == '/') || (filename[a] == '\\') ) {
00126                      filename[a] = '_';
00127               }
00128        }
00129        snprintf(pathname, sizeof pathname, "./files/%s/%s",
00130                CC->room.QRdirname, filename);
00131        if (access(pathname, 0) != 0) {
00132               cprintf("%d File '%s' not found.\n",
00133                      ERROR + FILE_NOT_FOUND, pathname);
00134               return;
00135        }
00136 
00137        if (CtdlGetRoom(&qrbuf, newroom) != 0) {
00138               cprintf("%d '%s' does not exist.\n", ERROR + ROOM_NOT_FOUND, newroom);
00139               return;
00140        }
00141        if ((qrbuf.QRflags & QR_DIRECTORY) == 0) {
00142               cprintf("%d '%s' is not a directory room.\n",
00143                      ERROR + NOT_HERE, qrbuf.QRname);
00144               return;
00145        }
00146        snprintf(newpath, sizeof newpath, "./files/%s/%s", qrbuf.QRdirname,
00147                filename);
00148        if (link(pathname, newpath) != 0) {
00149               cprintf("%d Couldn't move file: %s\n", ERROR + INTERNAL_ERROR,
00150                      strerror(errno));
00151               return;
00152        }
00153        unlink(pathname);
00154 
00155        /* this is a crude method of copying the file description */
00156        snprintf(buf, sizeof buf,
00157                "cat ./files/%s/filedir |grep \"%s\" >>./files/%s/filedir",
00158                CC->room.QRdirname, filename, qrbuf.QRdirname);
00159        system(buf);
00160        cprintf("%d File '%s' has been moved.\n", CIT_OK, filename);
00161 }
00162 
00163 
00164 /*
00165  * This code is common to all commands which open a file for downloading,
00166  * regardless of whether it's a file from the directory, an image, a network
00167  * spool file, a MIME attachment, etc.
00168  * It examines the file and displays the OK result code and some information
00169  * about the file.  NOTE: this stuff is Unix dependent.
00170  */
00171 void OpenCmdResult(char *filename, const char *mime_type)
00172 {
00173        struct stat statbuf;
00174        time_t modtime;
00175        long filesize;
00176 
00177        fstat(fileno(CC->download_fp), &statbuf);
00178        CC->download_fp_total = statbuf.st_size;
00179        filesize = (long) statbuf.st_size;
00180        modtime = (time_t) statbuf.st_mtime;
00181 
00182        cprintf("%d %ld|%ld|%s|%s\n",
00183               CIT_OK, filesize, (long)modtime, filename, mime_type);
00184 }
00185 
00186 
00187 /*
00188  * open a file for downloading
00189  */
00190 void cmd_open(char *cmdbuf)
00191 {
00192        char filename[256];
00193        char pathname[PATH_MAX];
00194        int a;
00195 
00196        extract_token(filename, cmdbuf, 0, '|', sizeof filename);
00197 
00198        if (CtdlAccessCheck(ac_logged_in)) return;
00199 
00200        if ((CC->room.QRflags & QR_DIRECTORY) == 0) {
00201               cprintf("%d No directory in this room.\n",
00202                      ERROR + NOT_HERE);
00203               return;
00204        }
00205 
00206        if (IsEmptyStr(filename)) {
00207               cprintf("%d You must specify a file name.\n",
00208                      ERROR + FILE_NOT_FOUND);
00209               return;
00210        }
00211 
00212        if (CC->download_fp != NULL) {
00213               cprintf("%d You already have a download file open.\n",
00214                      ERROR + RESOURCE_BUSY);
00215               return;
00216        }
00217 
00218        for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
00219               if ( (filename[a] == '/') || (filename[a] == '\\') ) {
00220                      filename[a] = '_';
00221               }
00222        }
00223 
00224        snprintf(pathname, sizeof pathname,
00225                       "%s/%s/%s",
00226                       ctdl_file_dir,
00227                       CC->room.QRdirname, filename);
00228        CC->download_fp = fopen(pathname, "r");
00229 
00230        if (CC->download_fp == NULL) {
00231               cprintf("%d cannot open %s: %s\n",
00232                      ERROR + INTERNAL_ERROR, pathname, strerror(errno));
00233               return;
00234        }
00235 
00236        OpenCmdResult(filename, "application/octet-stream");
00237 }
00238 
00239 /*
00240  * open an image file
00241  */
00242 void cmd_oimg(char *cmdbuf)
00243 {
00244        char filename[256];
00245        char pathname[PATH_MAX];
00246        char MimeTestBuf[32];
00247        struct ctdluser usbuf;
00248        char which_user[USERNAME_SIZE];
00249        int which_floor;
00250        int a;
00251        int rv;
00252 
00253        extract_token(filename, cmdbuf, 0, '|', sizeof filename);
00254 
00255        if (IsEmptyStr(filename)) {
00256               cprintf("%d You must specify a file name.\n",
00257                      ERROR + FILE_NOT_FOUND);
00258               return;
00259        }
00260 
00261        if (CC->download_fp != NULL) {
00262               cprintf("%d You already have a download file open.\n",
00263                      ERROR + RESOURCE_BUSY);
00264               return;
00265        }
00266 
00267        if (!strcasecmp(filename, "_userpic_")) {
00268               extract_token(which_user, cmdbuf, 1, '|', sizeof which_user);
00269               if (CtdlGetUser(&usbuf, which_user) != 0) {
00270                      cprintf("%d No such user.\n",
00271                             ERROR + NO_SUCH_USER);
00272                      return;
00273               }
00274               snprintf(pathname, sizeof pathname, 
00275                              "%s/%ld",
00276                              ctdl_usrpic_dir,
00277                              usbuf.usernum);
00278        } else if (!strcasecmp(filename, "_floorpic_")) {
00279               which_floor = extract_int(cmdbuf, 1);
00280               snprintf(pathname, sizeof pathname,
00281                              "%s/floor.%d",
00282                              ctdl_image_dir, which_floor);
00283        } else if (!strcasecmp(filename, "_roompic_")) {
00284               assoc_file_name(pathname, sizeof pathname, &CC->room, ctdl_image_dir);
00285        } else {
00286               for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
00287                      filename[a] = tolower(filename[a]);
00288                      if ( (filename[a] == '/') || (filename[a] == '\\') ) {
00289                             filename[a] = '_';
00290                      }
00291               }
00292               snprintf(pathname, sizeof pathname,
00293                              "%s/%s",
00294                              ctdl_image_dir,
00295                              filename);
00296        }
00297 
00298        CC->download_fp = fopen(pathname, "rb");
00299        if (CC->download_fp == NULL) {
00300               strcat(pathname, ".gif");
00301               CC->download_fp = fopen(pathname, "rb");
00302        }
00303        if (CC->download_fp == NULL) {
00304               cprintf("%d Cannot open %s: %s\n",
00305                      ERROR + FILE_NOT_FOUND, pathname, strerror(errno));
00306               return;
00307        }
00308        rv = fread(&MimeTestBuf[0], 1, 32, CC->download_fp);
00309        if (rv == -1) {
00310               cprintf("%d Cannot access %s: %s\n",
00311                      ERROR + FILE_NOT_FOUND, pathname, strerror(errno));
00312               return;
00313        }
00314 
00315        rewind (CC->download_fp);
00316        OpenCmdResult(pathname, GuessMimeType(&MimeTestBuf[0], 32));
00317 }
00318 
00319 /*
00320  * open a file for uploading
00321  */
00322 void cmd_uopn(char *cmdbuf)
00323 {
00324        int a;
00325 
00326        extract_token(CC->upl_file, cmdbuf, 0, '|', sizeof CC->upl_file);
00327        extract_token(CC->upl_mimetype, cmdbuf, 1, '|', sizeof CC->upl_mimetype);
00328        extract_token(CC->upl_comment, cmdbuf, 2, '|', sizeof CC->upl_comment);
00329 
00330        if (CtdlAccessCheck(ac_logged_in)) return;
00331 
00332        if ((CC->room.QRflags & QR_DIRECTORY) == 0) {
00333               cprintf("%d No directory in this room.\n",
00334                      ERROR + NOT_HERE);
00335               return;
00336        }
00337 
00338        if (IsEmptyStr(CC->upl_file)) {
00339               cprintf("%d You must specify a file name.\n",
00340                      ERROR + FILE_NOT_FOUND);
00341               return;
00342        }
00343 
00344        if (CC->upload_fp != NULL) {
00345               cprintf("%d You already have a upload file open.\n",
00346                      ERROR + RESOURCE_BUSY);
00347               return;
00348        }
00349 
00350        for (a = 0; !IsEmptyStr(&CC->upl_file[a]); ++a) {
00351               if ( (CC->upl_file[a] == '/') || (CC->upl_file[a] == '\\') ) {
00352                      CC->upl_file[a] = '_';
00353               }
00354        }
00355        snprintf(CC->upl_path, sizeof CC->upl_path, 
00356                       "%s/%s/%s",
00357                       ctdl_file_dir,
00358                       CC->room.QRdirname, CC->upl_file);
00359        snprintf(CC->upl_filedir, sizeof CC->upl_filedir,
00360                       "%s/%s/filedir", 
00361                       ctdl_file_dir,
00362                       CC->room.QRdirname);
00363 
00364        CC->upload_fp = fopen(CC->upl_path, "r");
00365        if (CC->upload_fp != NULL) {
00366               fclose(CC->upload_fp);
00367               CC->upload_fp = NULL;
00368               cprintf("%d '%s' already exists\n",
00369                      ERROR + ALREADY_EXISTS, CC->upl_path);
00370               return;
00371        }
00372 
00373        CC->upload_fp = fopen(CC->upl_path, "wb");
00374        if (CC->upload_fp == NULL) {
00375               cprintf("%d Cannot open %s: %s\n",
00376                      ERROR + INTERNAL_ERROR, CC->upl_path, strerror(errno));
00377               return;
00378        }
00379        cprintf("%d Ok\n", CIT_OK);
00380 }
00381 
00382 
00383 
00384 /*
00385  * open an image file for uploading
00386  */
00387 void cmd_uimg(char *cmdbuf)
00388 {
00389        int is_this_for_real;
00390        char basenm[256];
00391        int which_floor;
00392        int a;
00393 
00394        if (num_parms(cmdbuf) < 2) {
00395               cprintf("%d Usage error.\n", ERROR + ILLEGAL_VALUE);
00396               return;
00397        }
00398 
00399        is_this_for_real = extract_int(cmdbuf, 0);
00400        extract_token(CC->upl_mimetype, cmdbuf, 1, '|', sizeof CC->upl_mimetype);
00401        extract_token(basenm, cmdbuf, 2, '|', sizeof basenm);
00402        if (CC->upload_fp != NULL) {
00403               cprintf("%d You already have an upload file open.\n",
00404                      ERROR + RESOURCE_BUSY);
00405               return;
00406        }
00407 
00408        strcpy(CC->upl_path, "");
00409 
00410        for (a = 0; !IsEmptyStr(&basenm[a]); ++a) {
00411               basenm[a] = tolower(basenm[a]);
00412               if ( (basenm[a] == '/') || (basenm[a] == '\\') ) {
00413                      basenm[a] = '_';
00414               }
00415        }
00416 
00417        if (CC->user.axlevel >= AxAideU) {
00418               snprintf(CC->upl_path, sizeof CC->upl_path, 
00419                              "%s/%s",
00420                              ctdl_image_dir,
00421                              basenm);
00422        }
00423 
00424        if (!strcasecmp(basenm, "_userpic_")) {
00425               snprintf(CC->upl_path, sizeof CC->upl_path,
00426                              "%s/%ld.gif",
00427                              ctdl_usrpic_dir,
00428                              CC->user.usernum);
00429        }
00430 
00431        if ((!strcasecmp(basenm, "_floorpic_"))
00432            && (CC->user.axlevel >= AxAideU)) {
00433               which_floor = extract_int(cmdbuf, 2);
00434               snprintf(CC->upl_path, sizeof CC->upl_path,
00435                              "%s/floor.%d.gif",
00436                              ctdl_image_dir,
00437                              which_floor);
00438        }
00439 
00440        if ((!strcasecmp(basenm, "_roompic_")) && (is_room_aide())) {
00441               assoc_file_name(CC->upl_path, sizeof CC->upl_path, &CC->room, ctdl_image_dir);
00442        }
00443 
00444        if (IsEmptyStr(CC->upl_path)) {
00445               cprintf("%d Higher access required.\n",
00446                      ERROR + HIGHER_ACCESS_REQUIRED);
00447               return;
00448        }
00449 
00450        if (is_this_for_real == 0) {
00451               cprintf("%d Ok to send image\n", CIT_OK);
00452               return;
00453        }
00454 
00455        CC->upload_fp = fopen(CC->upl_path, "wb");
00456        if (CC->upload_fp == NULL) {
00457               cprintf("%d Cannot open %s: %s\n",
00458                      ERROR + INTERNAL_ERROR, CC->upl_path, strerror(errno));
00459               return;
00460        }
00461        cprintf("%d Ok\n", CIT_OK);
00462        CC->upload_type = UPL_IMAGE;
00463 }
00464 
00465 
00466 /*
00467  * close the download file
00468  */
00469 void cmd_clos(char *cmdbuf)
00470 {
00471        char buf[256];
00472 
00473        if (CC->download_fp == NULL) {
00474               cprintf("%d You don't have a download file open.\n",
00475                      ERROR + RESOURCE_NOT_OPEN);
00476               return;
00477        }
00478 
00479        fclose(CC->download_fp);
00480        CC->download_fp = NULL;
00481 
00482        if (CC->dl_is_net == 1) {
00483               CC->dl_is_net = 0;
00484               snprintf(buf, sizeof buf, 
00485                              "%s/%s",
00486                              ctdl_netout_dir,
00487                              CC->net_node);
00488               unlink(buf);
00489        }
00490 
00491        cprintf("%d Ok\n", CIT_OK);
00492 }
00493 
00494 
00495 /*
00496  * abort an upload
00497  */
00498 void abort_upl(CitContext *who)
00499 {
00500        if (who->upload_fp != NULL) {
00501               fclose(who->upload_fp);
00502               who->upload_fp = NULL;
00503               unlink(CC->upl_path);
00504        }
00505 }
00506 
00507 
00508 
00509 /*
00510  * close the upload file
00511  */
00512 void cmd_ucls(char *cmd)
00513 {
00514        FILE *fp;
00515        char upload_notice[512];
00516        static int seq = 0;
00517 
00518        if (CC->upload_fp == NULL) {
00519               cprintf("%d You don't have an upload file open.\n", ERROR + RESOURCE_NOT_OPEN);
00520               return;
00521        }
00522 
00523        fclose(CC->upload_fp);
00524        CC->upload_fp = NULL;
00525 
00526        if ((!strcasecmp(cmd, "1")) && (CC->upload_type != UPL_FILE)) {
00527               cprintf("%d Upload completed.\n", CIT_OK);
00528 
00529               if (CC->upload_type == UPL_NET) {
00530                      char final_filename[PATH_MAX];
00531                       snprintf(final_filename, sizeof final_filename,
00532                             "%s/%s.%04lx.%04x",
00533                             ctdl_netin_dir,
00534                             CC->net_node,
00535                             (long)getpid(),
00536                             ++seq
00537                      );
00538 
00539                      if (link(CC->upl_path, final_filename) == 0) {
00540                             unlink(CC->upl_path);
00541                      }
00542                      else {
00543                             syslog(LOG_ALERT, "Cannot link %s to %s: %s\n",
00544                                    CC->upl_path, final_filename, strerror(errno)
00545                             );
00546                      }
00547 
00548                      /* FIXME ... here we need to trigger a network run */
00549               }
00550 
00551               CC->upload_type = UPL_FILE;
00552               return;
00553        }
00554 
00555        if (!strcasecmp(cmd, "1")) {
00556               cprintf("%d File '%s' saved.\n", CIT_OK, CC->upl_path);
00557               fp = fopen(CC->upl_filedir, "a");
00558               if (fp == NULL) {
00559                      fp = fopen(CC->upl_filedir, "w");
00560               }
00561               if (fp != NULL) {
00562                      fprintf(fp, "%s %s %s\n", CC->upl_file,
00563                             CC->upl_mimetype,
00564                             CC->upl_comment);
00565                      fclose(fp);
00566               }
00567 
00568               /* put together an upload notice */
00569               snprintf(upload_notice, sizeof upload_notice,
00570                      "NEW UPLOAD: '%s'\n %s\n%s\n",
00571                       CC->upl_file, 
00572                       CC->upl_comment, 
00573                       CC->upl_mimetype);
00574               quickie_message(CC->curr_user, NULL, NULL, CC->room.QRname,
00575                             upload_notice, 0, NULL);
00576        } else {
00577               abort_upl(CC);
00578               cprintf("%d File '%s' aborted.\n", CIT_OK, CC->upl_path);
00579        }
00580 }
00581 
00582 
00583 /*
00584  * read from the download file
00585  */
00586 void cmd_read(char *cmdbuf)
00587 {
00588        long start_pos;
00589        size_t bytes;
00590        char buf[SIZ];
00591        int rc;
00592 
00593        /* The client will transmit its requested offset and byte count */
00594        start_pos = extract_long(cmdbuf, 0);
00595        bytes = extract_int(cmdbuf, 1);
00596        if ((start_pos < 0) || (bytes <= 0)) {
00597               cprintf("%d you have to specify a value > 0.\n", ERROR + ILLEGAL_VALUE);
00598               return;
00599        }
00600 
00601        if (CC->download_fp == NULL) {
00602               cprintf("%d You don't have a download file open.\n",
00603                      ERROR + RESOURCE_NOT_OPEN);
00604               return;
00605        }
00606 
00607        /* If necessary, reduce the byte count to the size of our buffer */
00608        if (bytes > sizeof(buf)) {
00609               bytes = sizeof(buf);
00610        }
00611 
00612        rc = fseek(CC->download_fp, start_pos, 0);
00613        if (rc < 0) {
00614               cprintf("%d your file is smaller then %ld.\n", ERROR + ILLEGAL_VALUE, start_pos);
00615               syslog(LOG_ALERT, "your file %s is smaller then %ld. [%s]\n", 
00616                      CC->upl_path, 
00617                      start_pos,
00618                      strerror(errno));
00619 
00620               return;
00621        }
00622        bytes = fread(buf, 1, bytes, CC->download_fp);
00623        if (bytes > 0) {
00624               /* Tell the client the actual byte count and transmit it */
00625               cprintf("%d %d\n", BINARY_FOLLOWS, (int)bytes);
00626               client_write(buf, bytes);
00627        }
00628        else {
00629               cprintf("%d %s\n", ERROR, strerror(errno));
00630        }
00631 }
00632 
00633 
00634 /*
00635  * write to the upload file
00636  */
00637 void cmd_writ(char *cmdbuf)
00638 {
00639        int bytes;
00640        char *buf;
00641        int rv;
00642 
00643        unbuffer_output();
00644 
00645        bytes = extract_int(cmdbuf, 0);
00646 
00647        if (CC->upload_fp == NULL) {
00648               cprintf("%d You don't have an upload file open.\n", ERROR + RESOURCE_NOT_OPEN);
00649               return;
00650        }
00651        if (bytes <= 0) {
00652               cprintf("%d you have to specify a value > 0.\n", ERROR + ILLEGAL_VALUE);
00653               return;
00654        }
00655 
00656        if (bytes > 100000) {
00657               bytes = 100000;
00658        }
00659 
00660        cprintf("%d %d\n", SEND_BINARY, bytes);
00661        buf = malloc(bytes + 1);
00662        client_read(buf, bytes);
00663        rv = fwrite(buf, bytes, 1, CC->upload_fp);
00664        if (rv == -1) {
00665               syslog(LOG_EMERG, "Couldn't write: %s\n",
00666                      strerror(errno));
00667        }
00668        free(buf);
00669 }
00670 
00671 
00672 
00673 
00674 /*
00675  * cmd_ndop() - open a network spool file for downloading
00676  */
00677 void cmd_ndop(char *cmdbuf)
00678 {
00679        char pathname[256];
00680        struct stat statbuf;
00681 
00682        if (IsEmptyStr(CC->net_node)) {
00683               cprintf("%d Not authenticated as a network node.\n",
00684                      ERROR + NOT_LOGGED_IN);
00685               return;
00686        }
00687 
00688        if (CC->download_fp != NULL) {
00689               cprintf("%d You already have a download file open.\n",
00690                      ERROR + RESOURCE_BUSY);
00691               return;
00692        }
00693 
00694        snprintf(pathname, sizeof pathname, 
00695                       "%s/%s",
00696                       ctdl_netout_dir,
00697                       CC->net_node);
00698 
00699        /* first open the file in append mode in order to create a
00700         * zero-length file if it doesn't already exist 
00701         */
00702        CC->download_fp = fopen(pathname, "a");
00703        if (CC->download_fp != NULL)
00704               fclose(CC->download_fp);
00705 
00706        /* now open it */
00707        CC->download_fp = fopen(pathname, "r");
00708        if (CC->download_fp == NULL) {
00709               cprintf("%d cannot open %s: %s\n",
00710                      ERROR + INTERNAL_ERROR, pathname, strerror(errno));
00711               return;
00712        }
00713 
00714 
00715        /* set this flag so other routines know that the download file
00716         * currently open is a network spool file 
00717         */
00718        CC->dl_is_net = 1;
00719 
00720        stat(pathname, &statbuf);
00721        CC->download_fp_total = statbuf.st_size;
00722        cprintf("%d %ld\n", CIT_OK, (long)statbuf.st_size);
00723 }
00724 
00725 /*
00726  * cmd_nuop() - open a network spool file for uploading
00727  */
00728 void cmd_nuop(char *cmdbuf)
00729 {
00730        static int seq = 1;
00731 
00732        if (IsEmptyStr(CC->net_node)) {
00733               cprintf("%d Not authenticated as a network node.\n",
00734                      ERROR + NOT_LOGGED_IN);
00735               return;
00736        }
00737 
00738        if (CC->upload_fp != NULL) {
00739               cprintf("%d You already have an upload file open.\n",
00740                      ERROR + RESOURCE_BUSY);
00741               return;
00742        }
00743 
00744        snprintf(CC->upl_path, sizeof CC->upl_path,
00745                       "%s/%s.%04lx.%04x",
00746                       ctdl_nettmp_dir,
00747                       CC->net_node, 
00748                       (long)getpid(), 
00749                       ++seq);
00750 
00751        CC->upload_fp = fopen(CC->upl_path, "r");
00752        if (CC->upload_fp != NULL) {
00753               fclose(CC->upload_fp);
00754               CC->upload_fp = NULL;
00755               cprintf("%d '%s' already exists\n",
00756                      ERROR + ALREADY_EXISTS, CC->upl_path);
00757               return;
00758        }
00759 
00760        CC->upload_fp = fopen(CC->upl_path, "w");
00761        if (CC->upload_fp == NULL) {
00762               cprintf("%d Cannot open %s: %s\n",
00763                      ERROR + INTERNAL_ERROR, CC->upl_path, strerror(errno));
00764               return;
00765        }
00766 
00767        CC->upload_type = UPL_NET;
00768        cprintf("%d Ok\n", CIT_OK);
00769 }
00770 
00771 
00772 /*****************************************************************************/
00773 /*                      MODULE INITIALIZATION STUFF                          */
00774 /*****************************************************************************/
00775 
00776 CTDL_MODULE_INIT(file_ops)
00777 {
00778        if (!threading) {
00779 
00780               CtdlRegisterProtoHook(cmd_delf, "DELF", "Delete a file");
00781               CtdlRegisterProtoHook(cmd_movf, "MOVF", "Move a file");
00782               CtdlRegisterProtoHook(cmd_open, "OPEN", "Open a download file transfer");
00783               CtdlRegisterProtoHook(cmd_clos, "CLOS", "Close a download file transfer");
00784               CtdlRegisterProtoHook(cmd_uopn, "UOPN", "Open an upload file transfer");
00785               CtdlRegisterProtoHook(cmd_ucls, "UCLS", "Close an upload file transfer");
00786               CtdlRegisterProtoHook(cmd_read, "READ", "File transfer read operation");
00787               CtdlRegisterProtoHook(cmd_writ, "WRIT", "File transfer write operation");
00788               CtdlRegisterProtoHook(cmd_ndop, "NDOP", "Open a network spool file for download");
00789               CtdlRegisterProtoHook(cmd_nuop, "NUOP", "Open a network spool file for upload");
00790               CtdlRegisterProtoHook(cmd_oimg, "OIMG", "Open an image file for download");
00791               CtdlRegisterProtoHook(cmd_uimg, "UIMG", "Upload an image file");
00792        }
00793         /* return our Subversion id for the Log */
00794        return "file_ops";
00795 }