afs_int32 SDISK_GetFile(struct rx_call *rxcall, afs_int32 file, struct ubik_version *version) { afs_int32 code; struct ubik_dbase *dbase; afs_int32 offset; struct ubik_stat ubikstat; char tbuffer[256]; afs_int32 tlen; afs_int32 length; if ((code = ubik_CheckAuth(rxcall))) { return code; } dbase = ubik_dbase; DBHOLD(dbase); code = (*dbase->stat) (dbase, file, &ubikstat); if (code < 0) { DBRELE(dbase); return code; } length = ubikstat.size; tlen = htonl(length); code = rx_Write(rxcall, (char *)&tlen, sizeof(afs_int32)); if (code != sizeof(afs_int32)) { DBRELE(dbase); ubik_dprint("Rx-write length error=%d\n", code); return BULK_ERROR; } offset = 0; while (length > 0) { tlen = (length > sizeof(tbuffer) ? sizeof(tbuffer) : length); code = (*dbase->read) (dbase, file, tbuffer, offset, tlen); if (code != tlen) { DBRELE(dbase); ubik_dprint("read failed error=%d\n", code); return UIOERROR; } code = rx_Write(rxcall, tbuffer, tlen); if (code != tlen) { DBRELE(dbase); ubik_dprint("Rx-write length error=%d\n", code); return BULK_ERROR; } length -= tlen; offset += tlen; } code = (*dbase->getlabel) (dbase, file, version); /* return the dbase, too */ DBRELE(dbase); return code; }
static bool_t xdrrx_putbytes(XDR *axdrs, caddr_t addr, u_int len) { afs_int32 code; XDR * xdrs = (XDR *)axdrs; struct rx_call *call = ((struct rx_call *)(xdrs)->x_private); #if defined(KERNEL) && defined(AFS_AIX32_ENV) char *saddr = (char *)&code; saddr -= STACK_TO_PIN; /* * Hack of hacks: Aix3.2 only guarantees that the next 2K of stack in pinned. Under * splnet (disables interrupts), which is set throughout rx, we can't swap in stack * pages if we need so we panic. Since sometimes, under splnet, we'll use more than * 2K stack we could try to bring the next few stack pages in here before we call the rx * layer. Of course this doesn't guarantee that those stack pages won't be swapped * out between here and calling splnet. So we now pin (and unpin) them instead to * guarantee that they remain there. */ if (pin(saddr, STACK_TO_PIN)) { /* XXX There's little we can do by continue XXX */ saddr = NULL; rx_pin_failed++; } #endif code = (rx_Write(call, addr, len) == len); #if defined(KERNEL) && defined(AFS_AIX32_ENV) if (saddr) unpin(saddr, STACK_TO_PIN); #endif return code; }
static void inform(struct Msg *m, int force) { if (LogLevel || force) Log("vol_split: %s", m->line); if (m->verbose || force) rx_Write(m->call, m->line, strlen(m->line)); }
static afs_uint32 xf_rxcall_do_write(XFILE * X, void *buf, afs_uint32 count) { struct rxinfo *i = X->refcon; afs_uint32 xcount; xcount = rx_Write(i->call, buf, count); if (xcount == count) return 0; i->code = rx_EndCall(i->call, 0); i->call = 0; return i->code; }
static int do_sendbytes(struct rx_call *call, afs_int32 bytes) { afs_int32 size; while (bytes > 0) { size = rxwrite_size; if (size > bytes) size = bytes; if (rx_Write(call, somebuf, size) != size) return 1; bytes -= size; } return 0; }
static afs_int32 StoreProc(struct rx_call *acall, char *string, int length) { afs_int32 tlen, code; while (length > 0) { tlen = (length > 256 ? 256 : length); code = rx_Write(acall, string, tlen); if (code != tlen) { return -1; } length -= tlen; } return 0; }
int bulk_SendFile(int fd, struct rx_call *call, struct stat *status) { char *buffer = (char *)0; int blockSize; long length; XDR xdr; long error = 0; blockSize = status->st_blksize; length = status->st_size; buffer = (char *)malloc(status->st_blksize); if (!buffer) { printf("malloc failed\n"); return BULK_ERROR; } xdrrx_create(&xdr, call, XDR_ENCODE); if (!xdr_long(&xdr, &length)) error = BULK_ERROR; while (!error && length) { int nbytes = (length > blockSize ? blockSize : length); nbytes = read(fd, buffer, nbytes); if (nbytes <= 0) { fprintf(stderr, "File system read failed\n"); break; } if (rx_Write(call, buffer, nbytes) != nbytes) break; length -= nbytes; } if (buffer) free(buffer); if (length) error = BULK_ERROR; return error; }
/*! * \brief Main interaction loop for the recovery manager * * The recovery light-weight process only runs when you're the * synchronization site. It performs the following tasks, if and only * if the prerequisite tasks have been performed successfully (it * keeps track of which ones have been performed in its bit map, * \p urecovery_state). * * First, it is responsible for probing that all servers are up. This * is the only operation that must be performed even if this is not * yet the sync site, since otherwise this site may not notice that * enough other machines are running to even elect this guy to be the * sync site. * * After that, the recovery process does nothing until the beacon and * voting modules manage to get this site elected sync site. * * After becoming sync site, recovery first attempts to find the best * database available in the network (it must do this in order to * ensure finding the latest committed data). After finding the right * database, it must fetch this dbase to the sync site. * * After fetching the dbase, it relabels it with a new version number, * to ensure that everyone recognizes this dbase as the most recent * dbase. * * One the dbase has been relabelled, this machine can start handling * requests. However, the recovery module still has one more task: * propagating the dbase out to everyone who is up in the network. */ void * urecovery_Interact(void *dummy) { afs_int32 code, tcode; struct ubik_server *bestServer = NULL; struct ubik_server *ts; int dbok, doingRPC, now; afs_int32 lastProbeTime; /* if we're the sync site, the best db version we've found yet */ static struct ubik_version bestDBVersion; struct ubik_version tversion; struct timeval tv; int length, tlen, offset, file, nbytes; struct rx_call *rxcall; char tbuffer[1024]; struct ubik_stat ubikstat; struct in_addr inAddr; char hoststr[16]; char pbuffer[1028]; int fd = -1; afs_int32 pass; afs_pthread_setname_self("recovery"); /* otherwise, begin interaction */ urecovery_state = 0; lastProbeTime = 0; while (1) { /* Run through this loop every 4 seconds */ tv.tv_sec = 4; tv.tv_usec = 0; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &tv); #else IOMGR_Select(0, 0, 0, 0, &tv); #endif ubik_dprint("recovery running in state %x\n", urecovery_state); /* Every 30 seconds, check all the down servers and mark them * as up if they respond. When a server comes up or found to * not be current, then re-find the the best database and * propogate it. */ if ((now = FT_ApproxTime()) > 30 + lastProbeTime) { for (ts = ubik_servers, doingRPC = 0; ts; ts = ts->next) { UBIK_BEACON_LOCK; if (!ts->up) { UBIK_BEACON_UNLOCK; doingRPC = 1; code = DoProbe(ts); if (code == 0) { UBIK_BEACON_LOCK; ts->up = 1; UBIK_BEACON_UNLOCK; DBHOLD(ubik_dbase); urecovery_state &= ~UBIK_RECFOUNDDB; DBRELE(ubik_dbase); } } else { UBIK_BEACON_UNLOCK; DBHOLD(ubik_dbase); if (!ts->currentDB) urecovery_state &= ~UBIK_RECFOUNDDB; DBRELE(ubik_dbase); } } if (doingRPC) now = FT_ApproxTime(); lastProbeTime = now; } /* Mark whether we are the sync site */ DBHOLD(ubik_dbase); if (!ubeacon_AmSyncSite()) { urecovery_state &= ~UBIK_RECSYNCSITE; DBRELE(ubik_dbase); continue; /* nothing to do */ } urecovery_state |= UBIK_RECSYNCSITE; /* If a server has just come up or if we have not found the * most current database, then go find the most current db. */ if (!(urecovery_state & UBIK_RECFOUNDDB)) { DBRELE(ubik_dbase); bestServer = (struct ubik_server *)0; bestDBVersion.epoch = 0; bestDBVersion.counter = 0; for (ts = ubik_servers; ts; ts = ts->next) { UBIK_BEACON_LOCK; if (!ts->up) { UBIK_BEACON_UNLOCK; continue; /* don't bother with these guys */ } UBIK_BEACON_UNLOCK; if (ts->isClone) continue; UBIK_ADDR_LOCK; code = DISK_GetVersion(ts->disk_rxcid, &ts->version); UBIK_ADDR_UNLOCK; if (code == 0) { /* perhaps this is the best version */ if (vcmp(ts->version, bestDBVersion) > 0) { /* new best version */ bestDBVersion = ts->version; bestServer = ts; } } } /* take into consideration our version. Remember if we, * the sync site, have the best version. Also note that * we may need to send the best version out. */ DBHOLD(ubik_dbase); if (vcmp(ubik_dbase->version, bestDBVersion) >= 0) { bestDBVersion = ubik_dbase->version; bestServer = (struct ubik_server *)0; urecovery_state |= UBIK_RECHAVEDB; } else { /* Clear the flag only when we know we have to retrieve * the db. Because urecovery_AllBetter() looks at it. */ urecovery_state &= ~UBIK_RECHAVEDB; } urecovery_state |= UBIK_RECFOUNDDB; urecovery_state &= ~UBIK_RECSENTDB; } if (!(urecovery_state & UBIK_RECFOUNDDB)) { DBRELE(ubik_dbase); continue; /* not ready */ } /* If we, the sync site, do not have the best db version, then * go and get it from the server that does. */ if ((urecovery_state & UBIK_RECHAVEDB) || !bestServer) { urecovery_state |= UBIK_RECHAVEDB; } else { /* we don't have the best version; we should fetch it. */ urecovery_AbortAll(ubik_dbase); /* Rx code to do the Bulk fetch */ file = 0; offset = 0; UBIK_ADDR_LOCK; rxcall = rx_NewCall(bestServer->disk_rxcid); ubik_print("Ubik: Synchronize database with server %s\n", afs_inet_ntoa_r(bestServer->addr[0], hoststr)); UBIK_ADDR_UNLOCK; code = StartDISK_GetFile(rxcall, file); if (code) { ubik_dprint("StartDiskGetFile failed=%d\n", code); goto FetchEndCall; } nbytes = rx_Read(rxcall, (char *)&length, sizeof(afs_int32)); length = ntohl(length); if (nbytes != sizeof(afs_int32)) { ubik_dprint("Rx-read length error=%d\n", code = BULK_ERROR); code = EIO; goto FetchEndCall; } /* give invalid label during file transit */ UBIK_VERSION_LOCK; tversion.epoch = 0; code = (*ubik_dbase->setlabel) (ubik_dbase, file, &tversion); UBIK_VERSION_UNLOCK; if (code) { ubik_dprint("setlabel io error=%d\n", code); goto FetchEndCall; } snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.TMP", ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file); fd = open(pbuffer, O_CREAT | O_RDWR | O_TRUNC, 0600); if (fd < 0) { code = errno; goto FetchEndCall; } code = lseek(fd, HDRSIZE, 0); if (code != HDRSIZE) { close(fd); goto FetchEndCall; } pass = 0; while (length > 0) { tlen = (length > sizeof(tbuffer) ? sizeof(tbuffer) : length); #ifndef AFS_PTHREAD_ENV if (pass % 4 == 0) IOMGR_Poll(); #endif nbytes = rx_Read(rxcall, tbuffer, tlen); if (nbytes != tlen) { ubik_dprint("Rx-read bulk error=%d\n", code = BULK_ERROR); code = EIO; close(fd); goto FetchEndCall; } nbytes = write(fd, tbuffer, tlen); pass++; if (nbytes != tlen) { code = UIOERROR; close(fd); goto FetchEndCall; } offset += tlen; length -= tlen; } code = close(fd); if (code) goto FetchEndCall; code = EndDISK_GetFile(rxcall, &tversion); FetchEndCall: tcode = rx_EndCall(rxcall, code); if (!code) code = tcode; if (!code) { /* we got a new file, set up its header */ urecovery_state |= UBIK_RECHAVEDB; UBIK_VERSION_LOCK; memcpy(&ubik_dbase->version, &tversion, sizeof(struct ubik_version)); snprintf(tbuffer, sizeof(tbuffer), "%s.DB%s%d", ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file); #ifdef AFS_NT40_ENV snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.OLD", ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file); code = unlink(pbuffer); if (!code) code = rename(tbuffer, pbuffer); snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.TMP", ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file); #endif if (!code) code = rename(pbuffer, tbuffer); if (!code) { (*ubik_dbase->open) (ubik_dbase, file); /* after data is good, sync disk with correct label */ code = (*ubik_dbase->setlabel) (ubik_dbase, 0, &ubik_dbase->version); } UBIK_VERSION_UNLOCK; #ifdef AFS_NT40_ENV snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.OLD", ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file); unlink(pbuffer); #endif } if (code) { unlink(pbuffer); /* * We will effectively invalidate the old data forever now. * Unclear if we *should* but we do. */ UBIK_VERSION_LOCK; ubik_dbase->version.epoch = 0; ubik_dbase->version.counter = 0; UBIK_VERSION_UNLOCK; ubik_print("Ubik: Synchronize database failed (error = %d)\n", code); } else { ubik_print("Ubik: Synchronize database completed\n"); urecovery_state |= UBIK_RECHAVEDB; } udisk_Invalidate(ubik_dbase, 0); /* data has changed */ #ifdef AFS_PTHREAD_ENV CV_BROADCAST(&ubik_dbase->version_cond); #else LWP_NoYieldSignal(&ubik_dbase->version); #endif } if (!(urecovery_state & UBIK_RECHAVEDB)) { DBRELE(ubik_dbase); continue; /* not ready */ } /* If the database was newly initialized, then when we establish quorum, write * a new label. This allows urecovery_AllBetter() to allow access for reads. * Setting it to 2 also allows another site to come along with a newer * database and overwrite this one. */ if (ubik_dbase->version.epoch == 1) { urecovery_AbortAll(ubik_dbase); UBIK_VERSION_LOCK; version_globals.ubik_epochTime = 2; ubik_dbase->version.epoch = version_globals.ubik_epochTime; ubik_dbase->version.counter = 1; code = (*ubik_dbase->setlabel) (ubik_dbase, 0, &ubik_dbase->version); UBIK_VERSION_UNLOCK; udisk_Invalidate(ubik_dbase, 0); /* data may have changed */ #ifdef AFS_PTHREAD_ENV CV_BROADCAST(&ubik_dbase->version_cond); #else LWP_NoYieldSignal(&ubik_dbase->version); #endif } /* Check the other sites and send the database to them if they * do not have the current db. */ if (!(urecovery_state & UBIK_RECSENTDB)) { /* now propagate out new version to everyone else */ dbok = 1; /* start off assuming they all worked */ /* * Check if a write transaction is in progress. We can't send the * db when a write is in progress here because the db would be * obsolete as soon as it goes there. Also, ops after the begin * trans would reach the recepient and wouldn't find a transaction * pending there. Frankly, I don't think it's possible to get past * the write-lock above if there is a write transaction in progress, * but then, it won't hurt to check, will it? */ if (ubik_dbase->flags & DBWRITING) { struct timeval tv; int safety = 0; long cur_usec = 50000; while ((ubik_dbase->flags & DBWRITING) && (safety < 500)) { DBRELE(ubik_dbase); /* sleep for a little while */ tv.tv_sec = 0; tv.tv_usec = cur_usec; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &tv); #else IOMGR_Select(0, 0, 0, 0, &tv); #endif cur_usec += 10000; safety++; DBHOLD(ubik_dbase); } } for (ts = ubik_servers; ts; ts = ts->next) { UBIK_ADDR_LOCK; inAddr.s_addr = ts->addr[0]; UBIK_ADDR_UNLOCK; UBIK_BEACON_LOCK; if (!ts->up) { UBIK_BEACON_UNLOCK; ubik_dprint("recovery cannot send version to %s\n", afs_inet_ntoa_r(inAddr.s_addr, hoststr)); dbok = 0; continue; } UBIK_BEACON_UNLOCK; ubik_dprint("recovery sending version to %s\n", afs_inet_ntoa_r(inAddr.s_addr, hoststr)); if (vcmp(ts->version, ubik_dbase->version) != 0) { ubik_dprint("recovery stating local database\n"); /* Rx code to do the Bulk Store */ code = (*ubik_dbase->stat) (ubik_dbase, 0, &ubikstat); if (!code) { length = ubikstat.size; file = offset = 0; UBIK_ADDR_LOCK; rxcall = rx_NewCall(ts->disk_rxcid); UBIK_ADDR_UNLOCK; code = StartDISK_SendFile(rxcall, file, length, &ubik_dbase->version); if (code) { ubik_dprint("StartDiskSendFile failed=%d\n", code); goto StoreEndCall; } while (length > 0) { tlen = (length > sizeof(tbuffer) ? sizeof(tbuffer) : length); nbytes = (*ubik_dbase->read) (ubik_dbase, file, tbuffer, offset, tlen); if (nbytes != tlen) { ubik_dprint("Local disk read error=%d\n", code = UIOERROR); goto StoreEndCall; } nbytes = rx_Write(rxcall, tbuffer, tlen); if (nbytes != tlen) { ubik_dprint("Rx-write bulk error=%d\n", code = BULK_ERROR); goto StoreEndCall; } offset += tlen; length -= tlen; } code = EndDISK_SendFile(rxcall); StoreEndCall: code = rx_EndCall(rxcall, code); } if (code == 0) { /* we set a new file, process its header */ ts->version = ubik_dbase->version; ts->currentDB = 1; } else dbok = 0; } else { /* mark file up to date */ ts->currentDB = 1; } } if (dbok) urecovery_state |= UBIK_RECSENTDB; } DBRELE(ubik_dbase); } return NULL; }
static void * client_thread( void *vparams) { struct client_data *params = (struct client_data *)vparams; struct rx_call *call; afs_int32 data; int i, j; afs_uint32 *readwrite; int readp = FALSE; afs_uint32 size; afs_uint32 num; for (i = 0; i < params->times; i++) { DBFPRINT(("starting command ")); call = rx_NewCall(params->conn); if (call == NULL) errx(1, "rx_NewCall failed"); data = htonl(RX_PERF_VERSION); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send version (err %d)", rx_Error(call)); data = htonl(params->command); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); data = htonl(rxread_size); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send read size (err %d)", rx_Error(call)); data = htonl(rxwrite_size); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send write read (err %d)", rx_Error(call)); switch (params->command) { case RX_PERF_RECV: DBFPRINT(("command ")); data = htonl(params->bytes); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); DBFPRINT(("sending(%d) ", params->bytes)); if (do_readbytes(call, params->bytes)) errx(1, "sendbytes (err %d)", rx_Error(call)); if (rx_Read32(call, &data) != 4) errx(1, "failed to read result from server (err %d)", rx_Error(call)); if (data != htonl(RXPERF_MAGIC_COOKIE)) warn("server send wrong magic cookie in responce"); DBFPRINT(("done\n")); break; case RX_PERF_SEND: DBFPRINT(("command ")); data = htonl(params->bytes); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); DBFPRINT(("sending(%d) ", params->bytes)); if (do_sendbytes(call, params->bytes)) errx(1, "sendbytes (err %d)", rx_Error(call)); if (rx_Read32(call, &data) != 4) errx(1, "failed to read result from server (err %d)", rx_Error(call)); if (data != htonl(RXPERF_MAGIC_COOKIE)) warn("server send wrong magic cookie in responce"); DBFPRINT(("done\n")); break; case RX_PERF_RPC: DBFPRINT(("commands ")); data = htonl(params->sendbytes); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); data = htonl(params->readbytes); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); DBFPRINT(("send(%d) ", params->sendbytes)); if (do_sendbytes(call, params->sendbytes)) errx(1, "sendbytes (err %d)", rx_Error(call)); DBFPRINT(("recv(%d) ", params->readbytes)); if (do_readbytes(call, params->readbytes)) errx(1, "sendbytes (err %d)", rx_Error(call)); if (rx_Read32(call, &data) != 4) errx(1, "failed to read result from server (err %d)", rx_Error(call)); if (data != htonl(RXPERF_MAGIC_COOKIE)) warn("server send wrong magic cookie in responce"); DBFPRINT(("done\n")); break; case RX_PERF_FILE: readfile(params->filename, &readwrite, &num); data = htonl(num); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); if (rx_Write(call, (char *)readwrite, num * sizeof(afs_uint32)) != num * sizeof(afs_uint32)) errx(1, "rx_Write failed to send list (err %d)", rx_Error(call)); for (j = 0; j < num; j++) { if (readwrite[j] == 0) readp = !readp; size = ntohl(readwrite[j]) * sizeof(afs_uint32); if (readp) { if (do_readbytes(call, size)) errx(1, "sendbytes (err %d)", rx_Error(call)); DBFPRINT(("read\n")); } else { if (do_sendbytes(call, size)) errx(1, "sendbytes (err %d)", rx_Error(call)); DBFPRINT(("send\n")); } } break; default: abort(); } rx_EndCall(call, 0); } #ifdef AFS_PTHREAD_ENV pthread_exit(NULL); #endif return NULL; }
/* this is not yet 64-bit clean */ ssize_t afscp_PWrite(const struct afscp_venusfid * fid, const void *buffer, size_t count, off_t offset) { struct AFSFetchStatus fst; struct AFSStoreStatus sst; struct AFSVolSync vs; struct AFSCallBack cb; struct AFSFid tf = fid->fid; struct afscp_volume *vol; struct afscp_server *server; struct rx_call *c = NULL; int code, code2 = 0; int i, j, bytes, totalbytes = 0; int bytesremaining; const char *p; off_t filesize; time_t now; vol = afscp_VolumeById(fid->cell, fid->fid.Volume); if (vol == NULL) { afscp_errno = ENOENT; return -1; } if (vol->voltype != RWVOL) { afscp_errno = EROFS; return -1; } code = ENOENT; for (i = 0; i < vol->nservers; i++) { server = afscp_ServerByIndex(vol->servers[i]); if (server && server->naddrs > 0) { for (j = 0; j < server->naddrs; j++) { code = RXAFS_FetchStatus(server->conns[j], &tf, &fst, &cb, &vs); if (code != 0) continue; sst.Mask = AFS_SETMODTIME; time(&now); sst.ClientModTime = now; filesize = fst.Length; if (offset + count > filesize) filesize = offset + count; c = rx_NewCall(server->conns[j]); if (c != 0) { p = buffer; code = StartRXAFS_StoreData(c, &tf, &sst, offset, count, filesize); if (code != 0) { code = rx_EndCall(c, code); continue; } /* * seems to write file length to beginning of file -- why? */ /* * bytesremaining = htonl(count); * bytes = rx_Write(c, (char *)&bytesremaining, * sizeof(afs_int32)); * if (bytes != sizeof(afs_int32)) { * code = rx_EndCall(c, bytes); * continue; * } */ bytesremaining = count; totalbytes = 0; while (bytesremaining > 0) { bytes = rx_Write(c, (char *)p, bytesremaining); if (bytes <= 0) break; p += bytes; totalbytes += bytes; bytesremaining -= bytes; } if (bytesremaining == 0) { code2 = EndRXAFS_StoreData(c, &fst, &vs); } code = rx_EndCall(c, code2); } if (code == 0) { return totalbytes; } } } } afscp_errno = code; return -1; }
int main(int argc, char **argv) { 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, (int)(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); }
int main(int argc, char **argv) { char *hostname; struct hostent *hostent; afs_uint32 host; int logstdout = 0; struct rx_connection *conn; struct rx_call *call; struct rx_peer *peer; int err = 0; int nCalls = 1, nBytes = 1; int bufferSize = 4000000; char *buffer; char *sendFile = 0; int setFD = 0; int jumbo = 0; #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV) setlinebuf(stdout); rxi_syscallp = test_syscall; #endif argv++; argc--; while (argc && **argv == '-') { if (strcmp(*argv, "-silent") == 0) print = 0; if (strcmp(*argv, "-jumbo") == 0) jumbo = 1; else if (strcmp(*argv, "-nc") == 0) nCalls = atoi(*++argv), argc--; else if (strcmp(*argv, "-nb") == 0) nBytes = atoi(*++argv), argc--; else if (strcmp(*argv, "-np") == 0) rx_nPackets = atoi(*++argv), argc--; else if (!strcmp(*argv, "-nsf")) rxi_nSendFrags = atoi(*++argv), argc--; else if (!strcmp(*argv, "-nrf")) rxi_nRecvFrags = atoi(*++argv), argc--; else if (strcmp(*argv, "-twind") == 0) rx_initSendWindow = atoi(*++argv), argc--; else if (strcmp(*argv, "-rwind") == 0) rx_initReceiveWindow = atoi(*++argv), argc--; else if (strcmp(*argv, "-rxlog") == 0) rxlog = 1; else if (strcmp(*argv, "-logstdout") == 0) logstdout = 1; else if (strcmp(*argv, "-eventlog") == 0) eventlog = 1; else if (strcmp(*argv, "-drop") == 0) { #ifdef RXDEBUG rx_intentionallyDroppedPacketsPer100 = atoi(*++argv), argc--; #else fprintf(stderr, "ERROR: Compiled without RXDEBUG\n"); #endif } else if (strcmp(*argv, "-burst") == 0) { burst = atoi(*++argv), argc--; burstTime.sec = atoi(*++argv), argc--; burstTime.usec = atoi(*++argv), argc--; } else if (strcmp(*argv, "-retry") == 0) { retryTime.sec = atoi(*++argv), argc--; retryTime.usec = atoi(*++argv), argc--; } else if (strcmp(*argv, "-timeout") == 0) timeout = atoi(*++argv), argc--; else if (strcmp(*argv, "-fill") == 0) fillPackets++; else if (strcmp(*argv, "-file") == 0) sendFile = *++argv, argc--; else if (strcmp(*argv, "-timereadvs") == 0) timeReadvs = 1; else if (strcmp(*argv, "-wait") == 0) { /* Wait time between calls--to test lastack code */ waitTime.sec = atoi(*++argv), argc--; waitTime.usec = atoi(*++argv), argc--; } else if (strcmp(*argv, "-compute") == 0) { /* Simulated "compute" time for each call--to test acknowledgement protocol. This is simulated by doing an iomgr_select: imperfect, admittedly. */ computeTime.sec = atoi(*++argv), argc--; computeTime.usec = atoi(*++argv), argc--; } else if (strcmp(*argv, "-fd") == 0) { /* Open at least this many fd's. */ setFD = atoi(*++argv), argc--; } else { err = 1; break; } argv++, argc--; } if (err || argc != 1) Quit("usage: rx_ctest [-silent] [-rxlog] [-eventlog] [-nc NCALLS] [-np NPACKETS] hostname"); hostname = *argv++, argc--; if (rxlog || eventlog) { if (logstdout) debugFile = stdout; else debugFile = fopen("rx_ctest.db", "w"); if (debugFile == NULL) Quit("Couldn't open rx_ctest.db"); if (rxlog) rx_debugFile = debugFile; if (eventlog) rxevent_debugFile = debugFile; } signal(SIGINT, intSignal); /*Changed to sigquit since dbx is broken right now */ #ifndef AFS_NT40_ENV signal(SIGQUIT, quitSignal); #endif #ifdef AFS_NT40_ENV if (afs_winsockInit() < 0) { printf("Can't initialize winsock.\n"); exit(1); } rx_EnableHotThread(); #endif rx_SetUdpBufSize(256 * 1024); if (!jumbo) rx_SetNoJumbo(); hostent = gethostbyname(hostname); if (!hostent) Abort("host %s not found", hostname); if (hostent->h_length != 4) Abort("host address is disagreeable length (%d)", hostent->h_length); memcpy((char *)&host, hostent->h_addr, sizeof(host)); if (setFD > 0) OpenFD(setFD); if (rx_Init(0) != 0) { printf("RX failed to initialize, exiting.\n"); exit(2); } if (setFD > 0) { printf("rx_socket=%d\n", rx_socket); } printf("Using %d packet buffers\n", rx_nPackets); conn = rx_NewConnection(host, htons(2500), 3, rxnull_NewClientSecurityObject(), 0); if (!conn) Abort("unable to make a new connection"); /* Set initial parameters. This is (currently) not the approved interface */ peer = rx_PeerOf(conn); if (burst) peer->burstSize = peer->burst = burst; if (!clock_IsZero(&burstTime)) peer->burstWait = burstTime; if (!clock_IsZero(&retryTime)) peer->rtt = _8THMSEC(&retryTime); if (sendFile) SendFile(sendFile, conn); else { buffer = (char *)osi_Alloc(bufferSize); while (nCalls--) { struct clock startTime; struct timeval t; int nbytes; int nSent; int bytesSent = 0; int bytesRead = 0; call = rx_NewCall(conn); if (!call) Abort("unable to make a new call"); clock_GetTime(&startTime); for (bytesSent = 0; bytesSent < nBytes; bytesSent += nSent) { int tryCount; tryCount = (bufferSize > nBytes - bytesSent) ? nBytes - bytesSent : bufferSize; nSent = rx_Write(call, buffer, tryCount); if (nSent == 0) break; } for (bytesRead = 0; (nbytes = rx_Read(call, buffer, bufferSize)); bytesRead += nbytes) { }; if (print) printf("Received %d characters in response\n", bytesRead); err = rx_EndCall(call, 0); if (err) printf("Error %d returned from rpc call\n", err); else { struct clock totalTime; float elapsedTime; clock_GetTime(&totalTime); clock_Sub(&totalTime, &startTime); elapsedTime = clock_Float(&totalTime); fprintf(stderr, "Sent %d bytes in %0.3f seconds: %0.0f bytes per second\n", bytesSent, elapsedTime, bytesSent / elapsedTime); } if (!clock_IsZero(&computeTime)) { t.tv_sec = computeTime.sec; t.tv_usec = computeTime.usec; if (select(0, 0, 0, 0, &t) != 0) Quit("Select didn't return 0"); } if (!clock_IsZero(&waitTime)) { struct timeval t; t.tv_sec = waitTime.sec; t.tv_usec = waitTime.usec; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &t); #else IOMGR_Sleep(t.tv_sec); #endif } if (debugFile) rx_PrintPeerStats(debugFile, rx_PeerOf(conn)); rx_PrintPeerStats(stdout, rx_PeerOf(conn)); } } Quit("testclient: done!\n"); return 0; }
int SendFile(char *file, struct rx_connection *conn) { struct rx_call *call; int fd; struct stat status; int blockSize, bytesLeft; char *buf; int nbytes; int err; struct clock startTime; int receivedStore = 0; struct clock totalReadvDelay; int nReadvs; int code; #ifdef AFS_AIX_ENV #include <sys/statfs.h> struct statfs tstatfs; #endif if (timeReadvs) { nReadvs = 0; clock_Zero(&totalReadvDelay); } fd = open(file, O_RDONLY, 0); if (fd < 0) Abort("Couldn't open %s\n", file); fstat(fd, &status); #ifdef AFS_NT40_ENV blockSize = 1024; #else #ifdef AFS_AIX_ENV /* Unfortunately in AIX valuable fields such as st_blksize are gone from the stat structure!! */ fstatfs(fd, &tstatfs); blockSize = tstatfs.f_bsize; #else blockSize = status.st_blksize; #endif #endif buf = (char *)osi_Alloc(blockSize); bytesLeft = status.st_size; clock_GetTime(&startTime); call = rx_NewCall(conn); while (bytesLeft) { if (!receivedStore && rx_GetRemoteStatus(call) == 79) { receivedStore = 1; fprintf(stderr, "Remote status indicates file accepted (\"received store\")\n"); } nbytes = (bytesLeft > blockSize ? blockSize : bytesLeft); errno = 0; code = read(fd, buf, nbytes); if (code != nbytes) { Abort("Only read %d bytes of %d, errno=%d\n", code, nbytes, errno); } code = rx_Write(call, buf, nbytes); if (code != nbytes) { Abort("Only wrote %d bytes of %d\n", code, nbytes); } bytesLeft -= nbytes; } while ((nbytes = rx_Read(call, buf, sizeof(buf))) > 0) { char *p = buf; while (nbytes--) { putchar(*p); p++; } } if ((err = rx_EndCall(call, 0)) != 0) { fprintf(stderr, "rx_Endcall returned error %d\n", err); } else { struct clock totalTime; float elapsedTime; clock_GetTime(&totalTime); clock_Sub(&totalTime, &startTime); elapsedTime = totalTime.sec + totalTime.usec / 1e6; fprintf(stderr, "Sent %d bytes in %0.3f seconds: %0.0f bytes per second\n", (int) status.st_size, elapsedTime, status.st_size / elapsedTime); if (timeReadvs) { float delay = clock_Float(&totalReadvDelay) / nReadvs; fprintf(stderr, "%d readvs, average delay of %0.4f seconds\n", nReadvs, delay); } } close(fd); return(0); }
static long Copious(struct client *c, char *buf, u_long buflen) { long code; struct rx_call *call; long i; long inlen = c->sendLen; long outlen = c->recvLen; long d = 23; long mysum; size_t outsum; mysum = 0; for (i = 0; i < inlen; i++) mysum += (d++ & 0xff); call = rx_NewCall(c->conn); code = StartRXKST_Copious(call, inlen, mysum, outlen); if (code == 0) { long tlen; long xfer = 0; long n; d = 23; while (xfer < inlen) { tlen = inlen - xfer; if (tlen > buflen) tlen = buflen; for (i = 0; i < tlen; i++) buf[i] = (d++ & 0xff); n = rx_Write(call, buf, tlen); if (n != tlen) { if (n < 0) code = n; else code = RXKST_WRITESHORT; break; } xfer += tlen; } if (code == 0) { xfer = 0; mysum = 0; while (xfer < outlen) { tlen = outlen - xfer; if (tlen > buflen) tlen = buflen; n = rx_Read(call, buf, tlen); if (n != tlen) { if (n < 0) code = n; else code = RXKST_READSHORT; break; } for (i = 0; i < tlen; i++) mysum += buf[i]; xfer += tlen; } } } if (code == 0) code = EndRXKST_Copious(call, &outsum); code = rx_EndCall(call, code); if (code) return code; if (outsum != mysum) { return RXKST_BADOUTPUTSUM; } return 0; }
afs_int32 SDISK_GetFile(struct rx_call *rxcall, afs_int32 index, afs_int32 file, struct ubik_version *version) { afs_int32 code; struct ubik_dbase *dbase; afs_int32 offset; struct ubik_stat ubikstat; char tbuffer[256]; afs_int32 tlen; afs_int32 length; if ((code = ubik_CheckAuth(rxcall))) { return code; } /* temporarily disabled because it causes problems for migration tool. Hey, it's just * a sanity check, anyway. if (ubeacon_AmSyncSite()) { return UDEADLOCK; } */ if (!ubik_dbase[index]) { return ENOENT; } dbase = ubik_dbase[index]; DBHOLD(dbase); code = (*dbase->stat) (dbase, file, &ubikstat); if (code < 0) { DBRELE(dbase); return code; } length = ubikstat.size; tlen = htonl(length); code = rx_Write(rxcall, (char *)&tlen, sizeof(afs_int32)); if (code != sizeof(afs_int32)) { DBRELE(dbase); ubik_dprint("Rx-write length error=%d\n", code); return BULK_ERROR; } offset = 0; while (length > 0) { tlen = (length > sizeof(tbuffer) ? sizeof(tbuffer) : length); code = (*dbase->read) (dbase, file, tbuffer, offset, tlen); if (code != tlen) { DBRELE(dbase); ubik_dprint("read failed error=%d\n", code); return UIOERROR; } code = rx_Write(rxcall, tbuffer, tlen); if (code != tlen) { DBRELE(dbase); ubik_dprint("Rx-write length error=%d\n", code); return BULK_ERROR; } length -= tlen; offset += tlen; } code = (*dbase->getlabel) (dbase, file, version); /* return the dbase, too */ DBRELE(dbase); return code; }
afs_int32 SBOZO_GetLog(struct rx_call *acall, char *aname) { afs_int32 code; FILE *tfile; int tc; char *logpath; char buffer; char caller[MAXKTCNAMELEN]; /* Check access since 'aname' could specify a file outside of the * AFS log directory (which is bosserver's working directory). */ if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { code = BZACCESS; goto fail; } if (bozo_isrestricted && strchr(aname, '/') && strcmp(aname, AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH)) { code = BZACCESS; goto fail; } /* construct local path from canonical (wire-format) path */ if (ConstructLocalLogPath(aname, &logpath)) { return BZNOENT; } if (DoLogging) bozo_Log("%s is executing GetLog '%s'\n", caller, logpath); tfile = fopen(logpath, "r"); free(logpath); if (!tfile) { return BZNOENT; } while (1) { tc = getc(tfile); if (tc == 0) continue; /* our termination condition on other end */ if (tc == EOF) break; buffer = tc; if (rx_Write(acall, &buffer, 1) != 1) { fclose(tfile); code = BZNET; goto fail; } } /* all done, cleanup and return */ fclose(tfile); /* write out the end delimeter */ buffer = 0; if (rx_Write(acall, &buffer, 1) != 1) return BZNET; code = 0; fail: osi_auditU(acall, BOS_GetLogsEvent, code, AUD_END); return code; }