Make tests/afcp compile cleanly
[openafs.git] / src / tests / afscp.c
index 4bf5ce2..717e705 100644 (file)
 #include <fcntl.h>
 #include <sys/select.h>
 #include <sys/stat.h>
+#include <netdb.h>
 
 #include <afs/param.h>
 #include <afs/afsint.h>
+#define FSINT_COMMON_XG 1
+#include <afs/afscbint.h>
 #include <sys/ioctl.h>
 #include <afs/venus.h>
 #include <afs/cellconfig.h>
-#include <afs/afs.h>
+#include <afs/sys_prototypes.h>
+
+#include <afs/afs_consts.h>
 
 /*#include <rx/rxkad.h>*/
 #include <rx/rx_null.h>
+#include <rx/rx_prototypes.h>
 
 /*#include <krb.h>*/
-#include <com_err.h>
+#include <afs/com_err.h>
 
 struct VenusFid {
     afs_int32 Cell;
     struct AFSFid Fid;
 };
 
-int statfile(char *path, char *cellname, afs_uint32 *server, 
-             struct AFSFid *f)
+int
+statfile(char *path, char *cellname, afs_uint32 * server, struct AFSFid *f)
 {
-     
-     struct ViceIoctl v;
-     struct VenusFid vf;
-     afs_int32 srvbuf[MAXHOSTS];
-     int code;
-     
-     v.in=0;
-     v.in_size=0;
-     v.out=cellname;
-     v.out_size=MAXCELLCHARS;
-     if ((code=pioctl(path, VIOC_FILE_CELL_NAME, &v, 1)))
-          return code;
-     
-     v.out=(char *)&vf;
-     v.out_size=sizeof(struct VenusFid);
-     if ((code=pioctl(path, VIOCGETFID, &v, 1)))
-          return code;
-     memcpy(f,&vf.Fid, sizeof(struct AFSFid));
-     
-     v.out=(char *)srvbuf;
-     v.out_size=sizeof(srvbuf);
-     if ((code=pioctl(path, VIOCWHEREIS, &v, 1)))
-          return code;
-     if (v.out_size <= sizeof(afs_int32))
-          return EINVAL;
-     
-     memcpy(server, srvbuf, sizeof(afs_int32));
-     return 0;
+
+    struct ViceIoctl v;
+    struct VenusFid vf;
+    afs_int32 srvbuf[AFS_MAXHOSTS];
+    int code;
+
+    if (!strncmp(path, "@afs:", 5)) {
+       char *pdup, *p;
+       struct hostent *he;
+
+       pdup = strdup(path);
+       strtok(pdup, ":");
+
+       if (!(p = strtok(NULL, ":"))) {
+           free(pdup);
+           return -1;
+       }
+       strncpy(cellname, p, MAXCELLCHARS);
+
+       if (!(p = strtok(NULL, ":"))) {
+           free(pdup);
+           return -1;
+       }
+       he = gethostbyname(p);
+       if (!he) {
+           printf("Unknown host %s\n", p);
+           free(pdup);
+           return -1;
+       }
+       memcpy(server, he->h_addr, he->h_length);
+
+       if (!(p = strtok(NULL, ":"))) {
+           free(pdup);
+           return -1;
+       }
+       f->Volume = atoi(p);
+
+       if (!(p = strtok(NULL, ":"))) {
+           free(pdup);
+           return -1;
+       }
+       f->Vnode = atoi(p);
+
+       if (!(p = strtok(NULL, ":"))) {
+           free(pdup);
+           return -1;
+       }
+       f->Unique = atoi(p);
+
+       if (strtok(NULL, ":")) {
+           printf("Too much extra stuff after @afs:...\n");
+           free(pdup);
+           return -1;
+       }
+
+       return 0;
+    }
+
+    v.in = 0;
+    v.in_size = 0;
+    v.out = cellname;
+    v.out_size = MAXCELLCHARS;
+    if ((code = pioctl(path, VIOC_FILE_CELL_NAME, &v, 1)))
+       return code;
+
+    v.out = (char *)&vf;
+    v.out_size = sizeof(struct VenusFid);
+    if ((code = pioctl(path, VIOCGETFID, &v, 1)))
+       return code;
+    memcpy(f, &vf.Fid, sizeof(struct AFSFid));
+
+    v.out = (char *)srvbuf;
+    v.out_size = sizeof(srvbuf);
+    if ((code = pioctl(path, VIOCWHEREIS, &v, 1)))
+       return code;
+    if (v.out_size <= sizeof(afs_int32))
+       return EINVAL;
+
+    memcpy(server, srvbuf, sizeof(afs_int32));
+    return 0;
 }
 
 
-extern int RXAFSCB_ExecuteRequest();
 struct rx_securityClass *sc;
 
-extern int start_cb_server() 
+extern int
+start_cb_server(void)
 {
-     struct rx_service *s;
-
-     sc=rxnull_NewServerSecurityObject();
-     s=rx_NewService(0,1,"afs", &sc, 1, RXAFSCB_ExecuteRequest);
-     if (!s)
-          return 1;
-     rx_StartServer(0);
-     return 0;
+    struct rx_service *s;
+
+    sc = rxnull_NewServerSecurityObject();
+    s = rx_NewService(0, 1, "afs", &sc, 1, RXAFSCB_ExecuteRequest);
+    if (!s)
+       return 1;
+    rx_StartServer(0);
+    return 0;
 }
 
 
 /*extern int rx_socket;*/
 extern unsigned short rx_port;
-int do_rx_Init(void)
+int
+do_rx_Init(void)
 {
-     struct sockaddr_in s;
-     int len;
-
-     if (rx_Init(0)) {
-          fprintf(stderr, "Cannot initialize rx\n");
-          return 1;
-     }
-
-     len=sizeof(struct sockaddr_in);
-     if (getsockname(rx_socket, &s, &len)) {
-          perror("getsockname");
-          return 1;
-     }
-     rx_port=ntohs(s.sin_port);
-
-     return 0;
+    struct sockaddr_in s;
+    int len;
+
+    if (rx_Init(0)) {
+       fprintf(stderr, "Cannot initialize rx\n");
+       return 1;
+    }
+
+    len = sizeof(struct sockaddr_in);
+    if (getsockname(rx_socket, (struct sockaddr *)&s, (socklen_t *)&len)) {
+       perror("getsockname");
+       return 1;
+    }
+    rx_port = ntohs(s.sin_port);
+
+    return 0;
 }
 
-struct rx_securityClass *get_sc(char * cellname) 
+struct rx_securityClass *
+get_sc(char *cellname)
 {
 #if 0
-     char realm[REALM_SZ];
-     CREDENTIALS c;
+    char realm[REALM_SZ];
+    CREDENTIALS c;
 #endif
-     
-     return rxnull_NewClientSecurityObject();
-#if 0     
-
-     ucstring(realm, cellname, REALM_SZ);
-     
-     if (krb_get_cred("afs", "", realm, &c)) {
-          if (get_ad_tkt("afs","",realm, DEFAULT_TKT_LIFE)) {
-               return NULL;
-          } else {
-               if (krb_get_cred("afs", "", realm, &c)) {
-                    return NULL;
-               }
-          }
-     }
-     
-     return rxkad_NewClientSecurityObject(rxkad_clear, c.session, c.kvno, 
-                                          c.ticket_st.length, c.ticket_st.dat);
+
+    return rxnull_NewClientSecurityObject();
+#if 0
+
+    ucstring(realm, cellname, REALM_SZ);
+
+    if (krb_get_cred("afs", "", realm, &c)) {
+       if (get_ad_tkt("afs", "", realm, DEFAULT_TKT_LIFE)) {
+           return NULL;
+       } else {
+           if (krb_get_cred("afs", "", realm, &c)) {
+               return NULL;
+           }
+       }
+    }
+
+    return rxkad_NewClientSecurityObject(rxkad_clear, c.session, c.kvno,
+                                        c.ticket_st.length, c.ticket_st.dat);
 #endif
 }
 
@@ -131,370 +191,412 @@ struct rx_securityClass *get_sc(char * cellname)
 #define scindex_RXKAD 2
 
 #define scindex scindex_RXKAD
-int main(int argc, char **argv) 
+int
+main(int argc, char **argv)
 {
-     char scell[MAXCELLCHARS], dcell[MAXCELLCHARS];
-     afs_uint32 ssrv, dsrv;
-     char *databuffer,*srcf,*destd,*destf,*destpath;
-     struct stat statbuf;
-     
-     struct AFSStoreStatus sst;
-     struct AFSFetchStatus fst,dfst;
-     struct AFSVolSync vs;
-     struct AFSCallBack scb,dcb;
-     struct AFSFid sf, dd, df;
-    
-     int filesz;
-     int ch, blksize, bytesremaining, bytes;
-     struct timeval start, finish;
-     struct timezone tz;
-     struct rx_securityClass *ssc = 0, *dsc = 0;
-     int sscindex, dscindex;
-     struct rx_connection *sconn,*dconn;
-     struct rx_call *scall, *dcall;
-     int code,fetchcode,storecode,printcallerrs;
-     int slcl = 0, dlcl = 0;
-     int sfd, dfd, unauth = 0;
-
-     struct AFSCBFids theFids;
-     struct AFSCBs theCBs;
-
-
-     blksize=8*1024;
-     
-     while ((ch=getopt(argc, argv, "ioub:")) != -1) {
-          switch(ch)
-          {
-          case 'b':
-               blksize=atoi(optarg);
-               break;
-          case 'i':
-               slcl=1;
-               break;
-          case 'o':
-               dlcl=1;
-               break;
-          case 'a':
-               unauth=1;
-               break;
-          default:
-               exit(1);
-          }
-     }
-     
-
-     if (argc - optind < 2) {
-          fprintf(stderr, "Usage: afscp [-i|-o]] [-b xfersz] [-u] source dest\n");
-          fprintf(stderr, "  -b   Set block size\n");
-          fprintf(stderr, "  -i   Source is local (copy into AFS)\n");
-          fprintf(stderr, "  -o   Dest is local (copy out of AFS)\n");
-          fprintf(stderr, "  -u   Run unauthenticated\n");
-          exit(1);
-     }
-     srcf=argv[optind++];
-     destpath=argv[optind++];
-     destd=strdup(destpath);
-     if (!destd) {
-          perror("strdup");
-          exit(1);
-     }
-     if ((destf=strrchr(destd, '/'))) {
-          *destf++=0;
-     } else {
-          destf=destd;
-          destd=".";
-     }
-     
-     
-     if (!slcl && statfile(srcf, scell, &ssrv, &sf)) {
-          fprintf(stderr, "Cannot get attributes of %s\n", srcf);
-          exit(1);
-     }
-     if (!dlcl && statfile(destd, dcell, &dsrv, &dd)) {
-          fprintf(stderr, "Cannot get attributes of %s\n", destd);
-          exit(1);
-     }
-    
-     if ((databuffer=malloc(blksize)) == NULL) {
-          perror("malloc");
-          exit(1);
-     }
-     
-     if (do_rx_Init())
-          exit(1);
-
-     if (start_cb_server()) {
-          printf("Cannot start callback service\n");
-          goto Fail_rx;
-     }
-     
-     if (!slcl) {
-          sscindex=scindex_RXKAD;
-          if (unauth || (ssc=get_sc(scell)) == NULL) {
-               ssc=rxnull_NewClientSecurityObject();
-               sscindex=scindex_NULL;
-               /*printf("Cannot get authentication for cell %s; running unauthenticated\n", scell);*/
-          }
-               sscindex=scindex_NULL;
-
-          if ((sconn=rx_NewConnection(ssrv, htons(AFSCONF_FILEPORT), 1, ssc, 
-                                      sscindex))
-                ==NULL) {
-               struct in_addr s;
-               s.s_addr=ssrv;
-               printf("Cannot initialize rx connection to source server (%s)\n",
-                      inet_ntoa(s));
-               goto Fail_sc;
-          }
-     }
-     
-     if (!dlcl) {
-          if (!slcl && ssrv == dsrv) {
-               dconn=sconn;
-               dsc=NULL;
-          } else {
-               if (slcl || strcmp(scell, dcell)){
-                    dscindex=scindex_RXKAD;
-                    if (unauth || (dsc=get_sc(dcell)) == NULL) {
-                         dsc=rxnull_NewClientSecurityObject();
-                         dscindex=scindex_NULL;
-                         /*printf("Cannot get authentication for cell %s; running unauthenticated\n", dcell);*/
-                    }
-               dscindex=scindex_NULL;
-               } else {
-                    dsc=ssc;
-                    dscindex=sscindex;
-               }
-          
-               if ((dconn=rx_NewConnection(dsrv, htons(AFSCONF_FILEPORT), 1, dsc,
-                                           dscindex))
-                   ==NULL) {
-                    struct in_addr s;
-                    s.s_addr=dsrv;
-                    printf("Cannot initialize rx connection to dest server (%s)\n",
-                           inet_ntoa(s));
-                    goto Fail_sconn;
-               }
-          }
-     }
-     
-     
-     memset(&sst, 0, sizeof(struct AFSStoreStatus));
-     
-     if (dlcl) {
-          dfd = open(destpath, O_RDWR|O_CREAT|O_EXCL, 0666);
-          if (dfd < 0 && errno == EEXIST) {
-               printf("%s already exists, overwriting\n", destpath);
-               dfd = open(destpath, O_RDWR|O_TRUNC, 0666);
-               if (dfd < 0) {
-                    fprintf(stderr, "Cannot open %s (%s)\n", destpath,
-                            error_message(errno));
-                    goto Fail_dconn;
-               }
-          } else if (dfd < 0) {
-               fprintf(stderr, "Cannot open %s (%s)\n", destpath,
-                       error_message(errno));
-               goto Fail_dconn;
-          }
-     } else {
-          if ((code=RXAFS_CreateFile(dconn, &dd, destf, &sst, &df, &fst,
-                                     &dfst, &dcb, &vs))) {
-               if (code == EEXIST) {
-                    printf("%s already exits, overwriting\n", destpath);
-                    if (statfile(destpath, dcell, &dsrv, &df))
-                         fprintf(stderr, "Cannot get attributes of %s\n",
-                                 destpath);
-                    else
-                         code=0;
-               } else {
-                    printf("Cannot create %s (%s)\n", destpath,
-                           error_message(code));
-               if (code)
-                    goto Fail_dconn;
-               }
-          }
-     }
-
-     if (slcl) {
-          sfd = open(srcf, O_RDONLY, 0);
-          if (sfd < 0) {
-               fprintf(stderr, "Cannot open %s (%s)\n", srcf,
-                       error_message(errno));
-               goto Fail_dconn;
-          }
-          if (fstat(sfd, &statbuf) < 0) {
-               fprintf(stderr, "Cannot stat %s (%s)\n", srcf,
-                       error_message(errno));
-               close(sfd);
-               goto Fail_dconn;
-          }
-     } else {
-          if ((code=RXAFS_FetchStatus(sconn, &sf, &fst, &scb, &vs))) {
-               printf("Cannot fetchstatus of %d.%d (%s)\n", sf.Volume, sf.Vnode, 
-                      error_message(code));
-               goto Fail_dconn;
-          }
-     }
-     
-     
-
-     if (slcl) {
-          filesz=statbuf.st_size;
-     } else {
-          filesz=fst.Length;
-     }
-     
-     printcallerrs=0;
-     fetchcode=0;
-     storecode=0;
-     if (!slcl) scall=rx_NewCall(sconn);
-     if (!dlcl) dcall=rx_NewCall(dconn);
-     gettimeofday(&start, &tz);
-     
-     if (!slcl) {
-          if ((code = StartRXAFS_FetchData(scall, &sf, 0, filesz))) {
-               printf("Unable to fetch data from %s (%s)\n", srcf, 
-                      error_message(code));
-               goto Fail_call;
-          }
-     }
-
-     if (!dlcl) {
-          if (slcl) {
-               sst.Mask=AFS_SETMODTIME|AFS_SETMODE;
-               sst.ClientModTime=statbuf.st_mtime;
-               sst.UnixModeBits=statbuf.st_mode & ~(S_IFMT|S_ISUID|S_ISGID);
-          } else {
-               sst.Mask=AFS_SETMODTIME|AFS_SETMODE;
-               sst.ClientModTime=fst.ClientModTime;
-               sst.UnixModeBits=fst.UnixModeBits & ~(S_IFMT|S_ISUID|S_ISGID);
-          }
-     
-          if ((code = StartRXAFS_StoreData(dcall, &df, &sst, 0, filesz, filesz))) {
-               printf("Unable to store data to %s (%s)\n", destpath, 
-                      error_message(code));
-               goto Fail_call;
-          }
-     }
-
-     if (slcl) {
-          bytesremaining=statbuf.st_size;
-     } else {
-          rx_Read(scall,&bytesremaining,sizeof(afs_int32));
-          bytesremaining=ntohl(bytesremaining);
-     }
-     
-     while (bytesremaining >0) {
-          /*printf("%d bytes remaining\n",bytesremaining);*/
-          if (slcl) {
-               if ((bytes=read(sfd, databuffer,
-                                  min(blksize,bytesremaining)))<= 0) {
-                    fetchcode=errno;
-                    break;
-               }
-          } else {
-               if ((bytes=rx_Read(scall, databuffer,
-                                  min(blksize,bytesremaining)))<= 0)
-                    break;
-          }
-          if (dlcl) {
-               if (write(dfd, databuffer, bytes) != bytes) {
-                    storecode=errno;
-                    break;
-               }
-          } else {
-               if (rx_Write(dcall, databuffer, bytes) != bytes)
-                    break;
-          }
-          bytesremaining -= bytes;
-          /*printf("%d bytes copied\n",bytes);*/
-     }
-          
-
-     if (bytesremaining > 0) {
-          printf("Some network error occured while copying data\n");
-          goto Fail_call;
-     }
-     
-     if (!slcl) fetchcode = EndRXAFS_FetchData(scall, &fst, &scb, &vs);
-     if (!dlcl) storecode = EndRXAFS_StoreData(dcall, &fst, &vs);
-     printcallerrs=1;
- Fail_call:
-          
-     if (slcl) {
-          if (close(sfd) && !fetchcode) fetchcode = errno;
-     } else {
-          fetchcode = rx_EndCall(scall, fetchcode);
-     }
-     if (fetchcode && printcallerrs)
-          printf("Error returned from fetch: %s\n", error_message(fetchcode));
-
-     if (dlcl) {
-          if (close(dfd) && !storecode) storecode = errno;
-     } else {
-          storecode = rx_EndCall(dcall, storecode);
-     }
-     if (storecode && printcallerrs)
-          printf("Error returned from store: %s\n", error_message(storecode));
-     
-     gettimeofday(&finish, &tz);
-     
-     if (!slcl) {
-          theFids.AFSCBFids_len=1;
-          theFids.AFSCBFids_val=&sf;
-          theCBs.AFSCBs_len=1;
-          theCBs.AFSCBs_val=&scb;
-          scb.CallBackType = CB_DROPPED;
-          if ((code=RXAFS_GiveUpCallBacks(sconn, &theFids, &theCBs)))
-               printf("Could not give up source callback: %s\n",
-                      error_message(code));
-     }
-
-     if (!dlcl) {
-          theFids.AFSCBFids_len=1;
-          theFids.AFSCBFids_val=&df;
-          theCBs.AFSCBs_len=1;
-          theCBs.AFSCBs_val=&dcb;
-          dcb.CallBackType = CB_DROPPED;
-          if ((code=RXAFS_GiveUpCallBacks(dconn, &theFids, &theCBs)))
-               printf("Could not give up target callback: %s\n",
-                      error_message(code));
-     }
-
-     if (code==0)
-          code=storecode;
-     if (code==0)
-          code=fetchcode;
-     
- Fail_dconn:
-     if (!dlcl && (slcl || dconn != sconn))
-          rx_DestroyConnection(dconn);
- Fail_sconn:
-     if (!slcl) rx_DestroyConnection(sconn);
- Fail_sc:
-     if (dsc && dsc != ssc)
-          RXS_Close(dsc);
-     if (ssc) RXS_Close(ssc);
- Fail_rx:
-     rx_Finalize();
-     
-     free(databuffer);
-     if (printcallerrs) {
-          double rate,size,time;
-          if (finish.tv_sec == start.tv_sec) {
-               printf("Copied %d bytes in %d microseconds\n", filesz, finish.tv_usec
-                      -start.tv_usec);
-          } else {
-               printf("Copied %d bytes in %d seconds\n", filesz, finish.tv_sec
-                      -start.tv_sec);
-          }
-          
-          size=filesz/1024.0;
-          time=finish.tv_sec-start.tv_sec + (finish.tv_usec-start.tv_usec)/1e+06;
-          rate=size/time;
-          printf("Transfer rate %g Kbytes/sec\n", rate);
-     
-     }
-     
-     exit(code != 0);
+    char scell[MAXCELLCHARS], dcell[MAXCELLCHARS];
+    afs_uint32 ssrv, dsrv;
+    char *databuffer, *srcf = NULL, *destd = NULL, *destf = NULL, *destpath = NULL;
+    struct stat statbuf;
+
+    struct AFSStoreStatus sst;
+    struct AFSFetchStatus fst, dfst;
+    struct AFSVolSync vs;
+    struct AFSCallBack scb, dcb;
+    struct AFSFid sf, dd, df;
+
+    int filesz = 0;
+    int ch, blksize, bytesremaining, bytes;
+    struct timeval start, finish;
+    struct timezone tz;
+    struct rx_securityClass *ssc = 0, *dsc = 0;
+    int sscindex, dscindex;
+    struct rx_connection *sconn = NULL, *dconn = NULL;
+    struct rx_call *scall = NULL, *dcall = NULL;
+    int code = 0, fetchcode, storecode, printcallerrs = 0;
+    int slcl = 0, dlcl = 0, unlock = 0;
+    int sfd = 0, dfd = 0, unauth = 0;
+
+    struct AFSCBFids theFids;
+    struct AFSCBs theCBs;
+
+
+    blksize = 8 * 1024;
+
+    while ((ch = getopt(argc, argv, "iouUb:")) != -1) {
+       switch (ch) {
+       case 'b':
+           blksize = atoi(optarg);
+           break;
+       case 'i':
+           slcl = 1;
+           break;
+       case 'o':
+           dlcl = 1;
+           break;
+       case 'u':
+           unauth = 1;
+           break;
+       case 'U':
+           unlock = 1;
+           break;
+       default:
+           printf("Unknown option '%c'\n", ch);
+           exit(1);
+       }
+    }
+
+
+    if (argc - optind + unlock < 2) {
+       fprintf(stderr,
+               "Usage: afscp [-i|-o]] [-b xfersz] [-u] [-U] source [dest]\n");
+       fprintf(stderr, "  -b   Set block size\n");
+       fprintf(stderr, "  -i   Source is local (copy into AFS)\n");
+       fprintf(stderr, "  -o   Dest is local (copy out of AFS)\n");
+       fprintf(stderr, "  -u   Run unauthenticated\n");
+       fprintf(stderr, "  -U   Send an unlock request for source. (dest path not required)\n");
+       fprintf(stderr, "source and dest can be paths or specified as:\n");
+       fprintf(stderr, "     @afs:cellname:servername:volume:vnode:uniq\n");
+       exit(1);
+    }
+    srcf = argv[optind++];
+    if (!unlock) {
+       destpath = argv[optind++];
+       destd = strdup(destpath);
+       if (!destd) {
+           perror("strdup");
+           exit(1);
+       }
+       if ((destf = strrchr(destd, '/'))) {
+           *destf++ = 0;
+       } else {
+           destf = destd;
+           destd = ".";
+       }
+    } else if (slcl) {
+       fprintf(stderr, "-i and -U cannot be used together\n");
+    }
+
+    if (!slcl && statfile(srcf, scell, &ssrv, &sf)) {
+       fprintf(stderr, "Cannot get attributes of %s\n", srcf);
+       exit(1);
+    }
+    if (!unlock && !dlcl && statfile(destd, dcell, &dsrv, &dd)) {
+       fprintf(stderr, "Cannot get attributes of %s\n", destd);
+       exit(1);
+    }
+
+    if ((databuffer = malloc(blksize)) == NULL) {
+       perror("malloc");
+       exit(1);
+    }
+
+    if (do_rx_Init())
+       exit(1);
+
+    if (start_cb_server()) {
+       printf("Cannot start callback service\n");
+       goto Fail_rx;
+    }
+
+    if (!slcl) {
+       sscindex = scindex_RXKAD;
+       if (unauth || (ssc = get_sc(scell)) == NULL) {
+           ssc = rxnull_NewClientSecurityObject();
+           sscindex = scindex_NULL;
+           /*printf("Cannot get authentication for cell %s; running unauthenticated\n", scell); */
+       }
+       sscindex = scindex_NULL;
+
+       if ((sconn =
+            rx_NewConnection(ssrv, htons(AFSCONF_FILEPORT), 1, ssc,
+                             sscindex))
+           == NULL) {
+           struct in_addr s;
+           s.s_addr = ssrv;
+           printf("Cannot initialize rx connection to source server (%s)\n",
+                  inet_ntoa(s));
+           goto Fail_sc;
+       }
+    }
+
+    if (!dlcl && !unlock) {
+       if (!slcl && ssrv == dsrv) {
+           dconn = sconn;
+           dsc = NULL;
+       } else {
+           if (slcl || strcmp(scell, dcell)) {
+               dscindex = scindex_RXKAD;
+               if (unauth || (dsc = get_sc(dcell)) == NULL) {
+                   dsc = rxnull_NewClientSecurityObject();
+                   dscindex = scindex_NULL;
+                   /*printf("Cannot get authentication for cell %s; running unauthenticated\n", dcell); */
+               }
+               dscindex = scindex_NULL;
+           } else {
+               dsc = ssc;
+               dscindex = sscindex;
+           }
+
+           if ((dconn =
+                rx_NewConnection(dsrv, htons(AFSCONF_FILEPORT), 1, dsc,
+                                 dscindex))
+               == NULL) {
+               struct in_addr s;
+               s.s_addr = dsrv;
+               printf
+                   ("Cannot initialize rx connection to dest server (%s)\n",
+                    inet_ntoa(s));
+               goto Fail_sconn;
+           }
+       }
+    }
+
+
+    memset(&sst, 0, sizeof(struct AFSStoreStatus));
+
+    if (dlcl && !unlock) {
+       dfd = open(destpath, O_RDWR | O_CREAT | O_EXCL, 0666);
+       if (dfd < 0 && errno == EEXIST) {
+           printf("%s already exists, overwriting\n", destpath);
+           dfd = open(destpath, O_RDWR | O_TRUNC, 0666);
+           if (dfd < 0) {
+               fprintf(stderr, "Cannot open %s (%s)\n", destpath,
+                       afs_error_message(errno));
+               goto Fail_dconn;
+           }
+       } else if (dfd < 0) {
+           fprintf(stderr, "Cannot open %s (%s)\n", destpath,
+                   afs_error_message(errno));
+           goto Fail_dconn;
+       }
+    } else if (!unlock) {
+       if ((code =
+            RXAFS_CreateFile(dconn, &dd, destf, &sst, &df, &fst, &dfst, &dcb,
+                             &vs))) {
+           if (code == EEXIST) {
+               printf("%s already exits, overwriting\n", destpath);
+               if (statfile(destpath, dcell, &dsrv, &df))
+                   fprintf(stderr, "Cannot get attributes of %s\n",
+                           destpath);
+               else
+                   code = 0;
+           } else {
+               printf("Cannot create %s (%s)\n", destpath,
+                      afs_error_message(code));
+               if (code)
+                   goto Fail_dconn;
+           }
+       }
+    }
+
+    if (slcl) {
+       sfd = open(srcf, O_RDONLY, 0);
+       if (sfd < 0) {
+           fprintf(stderr, "Cannot open %s (%s)\n", srcf,
+                   afs_error_message(errno));
+           goto Fail_dconn;
+       }
+       if (fstat(sfd, &statbuf) < 0) {
+           fprintf(stderr, "Cannot stat %s (%s)\n", srcf,
+                   afs_error_message(errno));
+           close(sfd);
+           goto Fail_dconn;
+       }
+    } else {
+       if ((code = RXAFS_FetchStatus(sconn, &sf, &fst, &scb, &vs))) {
+           printf("Cannot fetchstatus of %d.%d (%s)\n", sf.Volume, sf.Vnode,
+                  afs_error_message(code));
+           goto Fail_dconn;
+       }
+    }
+
+
+
+    if (slcl) {
+       filesz = statbuf.st_size;
+    } else {
+       filesz = fst.Length;
+    }
+
+    printcallerrs = 0;
+    fetchcode = 0;
+    storecode = 0;
+    if (!slcl && !unlock)
+       scall = rx_NewCall(sconn);
+    if (!dlcl && !unlock)
+       dcall = rx_NewCall(dconn);
+    gettimeofday(&start, &tz);
+    if (unlock) {
+       if (fst.lockCount) {
+           printf("Sending 1 unlock for %s (%d locks)\n", srcf, fst.lockCount);
+           if ((code = RXAFS_ReleaseLock(sconn, &sf, &vs))) {
+               printf("Unable to unlock %s (%s)\n", srcf,
+                      afs_error_message(code));
+           }
+       } else {
+           printf("No locks for %s\n", srcf);
+       }
+       fetchcode = code;
+       goto Finish;
+    }
+
+    if (!slcl) {
+       if ((code = StartRXAFS_FetchData(scall, &sf, 0, filesz))) {
+           printf("Unable to fetch data from %s (%s)\n", srcf,
+                  afs_error_message(code));
+           goto Fail_call;
+       }
+    }
+
+    if (!dlcl) {
+       if (slcl) {
+           sst.Mask = AFS_SETMODTIME | AFS_SETMODE;
+           sst.ClientModTime = statbuf.st_mtime;
+           sst.UnixModeBits =
+               statbuf.st_mode & ~(S_IFMT | S_ISUID | S_ISGID);
+       } else {
+           sst.Mask = AFS_SETMODTIME | AFS_SETMODE;
+           sst.ClientModTime = fst.ClientModTime;
+           sst.UnixModeBits =
+               fst.UnixModeBits & ~(S_IFMT | S_ISUID | S_ISGID);
+       }
+
+       if ((code =
+            StartRXAFS_StoreData(dcall, &df, &sst, 0, filesz, filesz))) {
+           printf("Unable to store data to %s (%s)\n", destpath,
+                  afs_error_message(code));
+           goto Fail_call;
+       }
+    }
+
+    if (slcl) {
+       bytesremaining = statbuf.st_size;
+    } else {
+       rx_Read(scall, (char *)&bytesremaining, sizeof(afs_int32));
+       bytesremaining = ntohl(bytesremaining);
+    }
+
+    while (bytesremaining > 0) {
+       /*printf("%d bytes remaining\n",bytesremaining); */
+       if (slcl) {
+           if ((bytes =
+                read(sfd, databuffer, min(blksize, bytesremaining))) <= 0) {
+               fetchcode = errno;
+               break;
+           }
+       } else {
+           if ((bytes =
+                rx_Read(scall, databuffer,
+                        min(blksize, bytesremaining))) <= 0)
+               break;
+       }
+       if (dlcl) {
+           if (write(dfd, databuffer, bytes) != bytes) {
+               storecode = errno;
+               break;
+           }
+       } else {
+           if (rx_Write(dcall, databuffer, bytes) != bytes)
+               break;
+       }
+       bytesremaining -= bytes;
+       /*printf("%d bytes copied\n",bytes); */
+    }
+
+
+    if (bytesremaining > 0) {
+       printf("Some network error occured while copying data\n");
+       goto Fail_call;
+    }
+
+    if (!slcl)
+       fetchcode = EndRXAFS_FetchData(scall, &fst, &scb, &vs);
+    if (!dlcl)
+       storecode = EndRXAFS_StoreData(dcall, &fst, &vs);
+    printcallerrs = 1;
+  Fail_call:
+
+    if (slcl) {
+       if (close(sfd) && !fetchcode)
+           fetchcode = errno;
+    } else {
+       fetchcode = rx_EndCall(scall, fetchcode);
+    }
+    if (fetchcode && printcallerrs)
+       printf("Error returned from fetch: %s\n", afs_error_message(fetchcode));
+
+    if (dlcl) {
+       if (close(dfd) && !storecode)
+           storecode = errno;
+    } else if (!unlock) {
+       storecode = rx_EndCall(dcall, storecode);
+    }
+    if (storecode && printcallerrs)
+       printf("Error returned from store: %s\n", afs_error_message(storecode));
+Finish:
+    gettimeofday(&finish, &tz);
+
+    if (!slcl) {
+       theFids.AFSCBFids_len = 1;
+       theFids.AFSCBFids_val = &sf;
+       theCBs.AFSCBs_len = 1;
+       theCBs.AFSCBs_val = &scb;
+       scb.CallBackType = CB_DROPPED;
+       if ((code = RXAFS_GiveUpCallBacks(sconn, &theFids, &theCBs)))
+           printf("Could not give up source callback: %s\n",
+                  afs_error_message(code));
+    }
+
+    if (!dlcl) {
+       theFids.AFSCBFids_len = 1;
+       theFids.AFSCBFids_val = &df;
+       theCBs.AFSCBs_len = 1;
+       theCBs.AFSCBs_val = &dcb;
+       dcb.CallBackType = CB_DROPPED;
+       if ((code = RXAFS_GiveUpCallBacks(dconn, &theFids, &theCBs)))
+           printf("Could not give up target callback: %s\n",
+                  afs_error_message(code));
+    }
+
+    if (code == 0)
+       code = storecode;
+    if (code == 0)
+       code = fetchcode;
+
+  Fail_dconn:
+    if (!dlcl && !unlock && (slcl || dconn != sconn))
+       rx_DestroyConnection(dconn);
+  Fail_sconn:
+    if (!slcl)
+       rx_DestroyConnection(sconn);
+  Fail_sc:
+    if (dsc && dsc != ssc)
+       RXS_Close(dsc);
+    if (ssc)
+       RXS_Close(ssc);
+  Fail_rx:
+    rx_Finalize();
+
+    free(databuffer);
+    if (printcallerrs && !unlock) {
+       double rate, size, time;
+       if (finish.tv_sec == start.tv_sec) {
+           printf("Copied %d bytes in %d microseconds\n", filesz,
+                  finish.tv_usec - start.tv_usec);
+       } else {
+           printf("Copied %d bytes in %d seconds\n", filesz,
+                  (int)(finish.tv_sec - start.tv_sec));
+       }
+
+       size = filesz / 1024.0;
+       time =
+           finish.tv_sec - start.tv_sec + (finish.tv_usec -
+                                           start.tv_usec) / 1e+06;
+       rate = size / time;
+       printf("Transfer rate %g Kbytes/sec\n", rate);
+
+    }
+
+    exit(code != 0);
 }