static int do_volop(struct fssync_state * state, afs_int32 command, SYNC_response * res) { afs_int32 code; SYNC_PROTO_BUF_DECL(res_buf); SYNC_response res_l; if (!res) { res = &res_l; res->payload.len = SYNC_PROTO_MAX_LEN; res->payload.buf = res_buf; } fprintf(stderr, "calling FSYNC_VolOp with command code %d (%s)\n", command, FSYNC_com2string(command)); code = FSYNC_VolOp(state->vop->volume, state->vop->partName, command, state->reason, res); debug_response(code, res); VDisconnectFS(); return 0; }
/* Try to detect if the fileserver is DAFS, and if so, re-exec as the * DAFS-enabled fssync-debug (dafssync_debug). If we fail to detect or * exec, just try to proceed anyway as if the server is not DAFS */ static void dafs_prolog(void) { SYNC_response res; SYNC_PROTO_BUF_DECL(res_buf); afs_int32 code; char *dfssd; res.payload.len = SYNC_PROTO_MAX_LEN; res.payload.buf = res_buf; /* LISTVOLUMES is a no-op; we just want to get the response header flags * to see if the server reports itself as DAFS or not */ code = FSYNC_VolOp(0, NULL, FSYNC_VOL_LISTVOLUMES, FSYNC_WHATEVER, &res); if (code) { /* probably failed to contact the fileserver; later code will provide * some warning/error indication */ return; } if (!(res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS)) { /* fileserver is not DAFS, so we don't need to do anything */ return; } dfssd = afs_exec_alt(fssd_argc, fssd_argv, "da", NULL); fprintf(stderr, "\n*** server asserted demand attach extensions, but we failed\n" "*** to exec a DAFS-enabled fssync-debug '%s' (errno=%d);\n" "*** attempting to proceed without it.\n\n", dfssd, errno); free(dfssd); }
/** * gracefully disconnect a sync client handle. * * @param[in] state pointer to sync client handle * * @return operation status * @retval SYNC_OK success */ afs_int32 SYNC_closeChannel(SYNC_client_state * state) { afs_int32 code; SYNC_command com; SYNC_response res; SYNC_PROTO_BUF_DECL(ores); if (state->fd == -1) return SYNC_OK; memset(&com, 0, sizeof(com)); memset(&res, 0, sizeof(res)); res.payload.len = SYNC_PROTO_MAX_LEN; res.payload.buf = ores; com.hdr.command = SYNC_COM_CHANNEL_CLOSE; com.hdr.command_len = sizeof(SYNC_command_hdr); com.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN; /* in case the other end dropped, don't do any retries */ state->retry_limit = 0; state->hard_timeout = 0; SYNC_ask(state, &com, &res); SYNC_disconnect(state); return SYNC_OK; }
static int VolOpQuery(struct cmd_syndesc * as, void * rock) { struct state state; SYNC_PROTO_BUF_DECL(res_buf); SYNC_response res; FSSYNC_VolOp_info vop; int i; res.hdr.response_len = sizeof(res.hdr); res.payload.buf = res_buf; res.payload.len = SYNC_PROTO_MAX_LEN; common_prolog(as, &state); common_volop_prolog(as, &state); do_volop(&state, FSYNC_VOL_QUERY_VOP, &res); if (!(res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS)) { printf("*** file server not compiled with demand attach extensions.\n"); printf("*** pending volume operation metadata not available.\n"); } if (res.hdr.response == SYNC_OK) { memcpy(&vop, res.payload.buf, sizeof(FSSYNC_VolOp_info)); printf("pending_vol_op = {\n"); printf("\tcom = {\n"); printf("\t\tproto_version = %u\n", vop.com.proto_version); printf("\t\tpkt_seq = %u\n", vop.com.pkt_seq); printf("\t\tcom_seq = %u\n", vop.com.com_seq); printf("\t\tprogramType = %d (%s)\n", vop.com.programType, program_type_to_string(vop.com.programType)); printf("\t\tpid = %d\n", vop.com.pid); printf("\t\ttid = %d\n", vop.com.tid); printf("\t\tcommand = %d (%s)\n", vop.com.command, command_code_to_string(vop.com.command)); printf("\t\treason = %d (%s)\n", vop.com.reason, reason_code_to_string(vop.com.reason)); printf("\t\tcommand_len = %u\n", vop.com.command_len); printf("\t\tflags = 0x%x\n", vop.com.flags); printf("\t}\n"); printf("\tvop = {\n"); printf("\t\tvolume = %u\n", vop.vop.volume); if (afs_strnlen(vop.vop.partName, sizeof(vop.vop.partName)) < sizeof(vop.vop.partName)) { printf("\t\tpartName = '%s'\n", vop.vop.partName); } else { printf("\t\tpartName = (illegal string)\n"); } printf("\t}\n"); printf("}\n"); } return 0; }
/** * write a response structure to a sync socket. * * @param[in] state handle to server-side state object * @param[in] fd file descriptor on which to perform i/o * @param[in] res handle to response packet * * @return operation status * @retval SYNC_OK * @retval SYNC_COM_ERROR */ afs_int32 SYNC_putRes(SYNC_server_state_t * state, int fd, SYNC_response * res) { int n; afs_int32 code = SYNC_OK; SYNC_PROTO_BUF_DECL(buf); if (res->hdr.response_len > (sizeof(res->hdr) + res->payload.len)) { Log("SYNC_putRes: response_len field in response header inconsistent\n"); code = SYNC_COM_ERROR; goto done; } if (res->hdr.response_len > SYNC_PROTO_MAX_LEN) { Log("SYNC_putRes: internal SYNC buffer too small; please file a bug\n"); code = SYNC_COM_ERROR; goto done; } #ifdef AFS_DEMAND_ATTACH_FS res->hdr.flags |= SYNC_FLAG_DAFS_EXTENSIONS; #endif res->hdr.proto_version = state->proto_version; res->hdr.pkt_seq = ++state->pkt_seq; res->hdr.res_seq = ++state->res_seq; memcpy(buf, &res->hdr, sizeof(res->hdr)); if (res->payload.len) { memcpy(buf + sizeof(res->hdr), res->payload.buf, res->hdr.response_len - sizeof(res->hdr)); } #ifdef AFS_NT40_ENV n = send(fd, buf, res->hdr.response_len, 0); #else /* !AFS_NT40_ENV */ n = write(fd, buf, res->hdr.response_len); #endif /* !AFS_NT40_ENV */ if (res->hdr.response_len != n) { Log("SYNC_putRes: write failed\n"); res->hdr.response = SYNC_COM_ERROR; goto done; } done: return code; }
static int do_volop(struct state * state, afs_int32 command, SYNC_response * res) { afs_int32 code; SYNC_PROTO_BUF_DECL(res_buf); SYNC_response res_l; if (!res) { res = &res_l; res->payload.len = SYNC_PROTO_MAX_LEN; res->payload.buf = res_buf; } fprintf(stderr, "calling FSYNC_VolOp with command code %d (%s)\n", command, command_code_to_string(command)); code = FSYNC_VolOp(state->vop->volume, state->vop->partName, command, state->reason, res); switch (code) { case SYNC_OK: case SYNC_DENIED: break; default: fprintf(stderr, "possible sync protocol error. return code was %d\n", code); } fprintf(stderr, "FSYNC_VolOp returned %d (%s)\n", code, response_code_to_string(code)); fprintf(stderr, "protocol response code was %d (%s)\n", res->hdr.response, response_code_to_string(res->hdr.response)); fprintf(stderr, "protocol reason code was %d (%s)\n", res->hdr.reason, reason_code_to_string(res->hdr.reason)); VDisconnectFS(); }
static int VnQuery(struct cmd_syndesc * as, void * rock) { struct state state; SYNC_PROTO_BUF_DECL(res_buf); SYNC_response res; Vnode v; int hi, lo; res.hdr.response_len = sizeof(res.hdr); res.payload.buf = res_buf; res.payload.len = SYNC_PROTO_MAX_LEN; common_prolog(as, &state); vn_prolog(as, &state); do_vnqry(&state, &res); if (res.hdr.response == SYNC_OK) { memcpy(&v, res.payload.buf, sizeof(Volume)); printf("vnode = {\n"); printf("\tvid_hash = {\n"); printf("\t\tnext = 0x%lx\n", v.vid_hash.next); printf("\t\tprev = 0x%lx\n", v.vid_hash.prev); printf("\t}\n"); printf("\thashNext = 0x%lx\n", v.hashNext); printf("\tlruNext = 0x%lx\n", v.lruNext); printf("\tlruPrev = 0x%lx\n", v.lruPrev); printf("\thashIndex = %hu\n", v.hashIndex); printf("\tchanged_newTime = %u\n", (unsigned int) v.changed_newTime); printf("\tchanged_oldTime = %u\n", (unsigned int) v.changed_oldTime); printf("\tdelete = %u\n", (unsigned int) v.delete); printf("\tvnodeNumber = %u\n", v.vnodeNumber); printf("\tvolumePtr = 0x%lx\n", v.volumePtr); printf("\tnUsers = %u\n", v.nUsers); printf("\tcacheCheck = %u\n", v.cacheCheck); #ifdef AFS_DEMAND_ATTACH_FS if (!(res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS)) { printf("*** fssync-debug built to expect demand attach extensions. server asserted\n"); printf("*** that it was not compiled with demand attach turned on. please recompile\n"); printf("*** fssync-debug to match your server\n"); goto done; } printf("\tnReaders = %u\n", v.nReaders); printf("\tvn_state_flags = %s\n", vn_flags_to_string(v.vn_state_flags)); printf("\tvn_state = %s\n", vn_state_to_string(v.vn_state)); #else if (res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS) { printf("*** server asserted demand attach extensions. fssync-debug not built to\n"); printf("*** recognize those extensions. please recompile fssync-debug if you need\n"); printf("*** to dump dafs extended state\n"); goto done; } #endif /* !AFS_DEMAND_ATTACH_FS */ printf("\twriter = %u\n", v.writer); printf("\tvcp = 0x%lx\n", v.vcp); printf("\thandle = 0x%lx\n", v.handle); printf("\tdisk = {\n"); printf("\t\ttype = %u\n", v.disk.type); printf("\t\tcloned = %u\n", v.disk.cloned); printf("\t\tmodeBits = %u\n", v.disk.modeBits); printf("\t\tlinkCount = %d\n", v.disk.linkCount); printf("\t\tlength = %u\n", v.disk.length); printf("\t\tuniquifier = %u\n", v.disk.uniquifier); printf("\t\tdataVersion = %u\n", v.disk.dataVersion); printf("\t\tvn_ino_lo = %u\n", v.disk.vn_ino_lo); printf("\t\tunixModifyTime = %u\n", v.disk.unixModifyTime); printf("\t\tauthor = %u\n", v.disk.author); printf("\t\towner = %u\n", v.disk.owner); printf("\t\tparent = %u\n", v.disk.parent); printf("\t\tvnodeMagic = %u\n", v.disk.vnodeMagic); printf("\t\tlock = {\n"); printf("\t\t\tlockCount = %d\n", v.disk.lock.lockCount); printf("\t\t\tlockTime = %d\n", v.disk.lock.lockTime); printf("\t\t}\n"); printf("\t\tserverModifyTime = %u\n", v.disk.serverModifyTime); printf("\t\tgroup = %d\n", v.disk.group); printf("\t\tvn_ino_hi = %d\n", v.disk.vn_ino_hi); printf("\t\treserved6 = %u\n", v.disk.reserved6); printf("\t}\n"); printf("}\n"); }
static int VolHdrQuery(struct cmd_syndesc * as, void * rock) { struct state state; SYNC_PROTO_BUF_DECL(res_buf); SYNC_response res; VolumeDiskData v; int i; res.hdr.response_len = sizeof(res.hdr); res.payload.buf = res_buf; res.payload.len = SYNC_PROTO_MAX_LEN; common_prolog(as, &state); common_volop_prolog(as, &state); do_volop(&state, FSYNC_VOL_QUERY_HDR, &res); if (res.hdr.response == SYNC_OK) { memcpy(&v, res.payload.buf, sizeof(VolumeDiskData)); printf("VolumeDiskData = {\n"); printf("\tstamp = {\n"); printf("\t\tmagic = 0x%x\n", v.stamp.magic); printf("\t\tversion = %u\n", v.stamp.version); printf("\t}\n"); printf("\tid = %u\n", v.id); printf("\tname = '%s'\n", v.name); if (v.inUse != 0) { printf("\tinUse = %d (%s)\n", v.inUse, program_type_to_string(v.inUse)); } else { printf("\tinUse = %d (no)\n", v.inUse); } printf("\tinService = %d\n", v.inService); printf("\tblessed = %d\n", v.blessed); printf("\tneedsSalvaged = %d\n", v.needsSalvaged); printf("\tuniquifier = %u\n", v.uniquifier); printf("\ttype = %d\n", v.type); printf("\tparentId = %u\n", v.parentId); printf("\tcloneId = %u\n", v.cloneId); printf("\tbackupId = %u\n", v.backupId); printf("\trestoredFromId = %u\n", v.restoredFromId); printf("\tneedsCallback = %d\n", v.needsCallback); printf("\tdestroyMe = %d\n", v.destroyMe); printf("\tdontSalvage = %d\n", v.dontSalvage); printf("\tmaxquota = %d\n", v.maxquota); printf("\tminquota = %d\n", v.minquota); printf("\tmaxfiles = %d\n", v.maxfiles); printf("\taccountNumber = %u\n", v.accountNumber); printf("\towner = %u\n", v.owner); printf("\tfilecount = %d\n", v.filecount); printf("\tdiskused = %d\n", v.diskused); printf("\tdayUse = %d\n", v.dayUse); for (i = 0; i < 7; i++) { printf("\tweekUse[%d] = %d\n", i, v.weekUse[i]); } printf("\tdayUseDate = %u\n", v.dayUseDate); printf("\tcreationDate = %u\n", v.creationDate); printf("\taccessDate = %u\n", v.accessDate); printf("\tupdateDate = %u\n", v.updateDate); printf("\texpirationDate = %u\n", v.expirationDate); printf("\tbackupDate = %u\n", v.backupDate); printf("\tcopyDate = %u\n", v.copyDate); #ifdef OPENAFS_VOL_STATS printf("\tstat_initialized = %d\n", v.stat_initialized); #else printf("\tmtd = '%s'\n", v.motd); #endif printf("}\n"); } return 0; }
static int VolQuery(struct cmd_syndesc * as, void * rock) { struct state state; SYNC_PROTO_BUF_DECL(res_buf); SYNC_response res; Volume v; int hi, lo; res.hdr.response_len = sizeof(res.hdr); res.payload.buf = res_buf; res.payload.len = SYNC_PROTO_MAX_LEN; common_prolog(as, &state); common_volop_prolog(as, &state); do_volop(&state, FSYNC_VOL_QUERY, &res); if (res.hdr.response == SYNC_OK) { memcpy(&v, res.payload.buf, sizeof(Volume)); printf("volume = {\n"); printf("\thashid = %u\n", v.hashid); printf("\theader = 0x%x\n", v.header); printf("\tdevice = %d\n", v.device); printf("\tpartition = 0x%x\n", v.partition); printf("\tlinkHandle = 0x%x\n", v.linkHandle); printf("\tnextVnodeUnique = %u\n", v.nextVnodeUnique); printf("\tdiskDataHandle = 0x%x\n", v.diskDataHandle); printf("\tvnodeHashOffset = %u\n", v.vnodeHashOffset); printf("\tshuttingDown = %d\n", v.shuttingDown); printf("\tgoingOffline = %d\n", v.goingOffline); printf("\tcacheCheck = %u\n", v.cacheCheck); printf("\tnUsers = %d\n", v.nUsers); printf("\tneedsPutBack = %d\n", v.needsPutBack); printf("\tspecialStatus = %d\n", v.specialStatus); printf("\tupdateTime = %u\n", v.updateTime); printf("\tvnodeIndex[vSmall] = {\n"); printf("\t\thandle = 0x%x\n", v.vnodeIndex[vSmall].handle); printf("\t\tbitmap = 0x%x\n", v.vnodeIndex[vSmall].bitmap); printf("\t\tbitmapSize = %u\n", v.vnodeIndex[vSmall].bitmapSize); printf("\t\tbitmapOffset = %u\n", v.vnodeIndex[vSmall].bitmapOffset); printf("\t}\n"); printf("\tvnodeIndex[vLarge] = {\n"); printf("\t\thandle = 0x%x\n", v.vnodeIndex[vLarge].handle); printf("\t\tbitmap = 0x%x\n", v.vnodeIndex[vLarge].bitmap); printf("\t\tbitmapSize = %u\n", v.vnodeIndex[vLarge].bitmapSize); printf("\t\tbitmapOffset = %u\n", v.vnodeIndex[vLarge].bitmapOffset); printf("\t}\n"); #ifdef AFS_DEMAND_ATTACH_FS if (res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS) { printf("\tupdateTime = %u\n", v.updateTime); printf("\tattach_state = %s\n", vol_state_to_string(v.attach_state)); printf("\tattach_flags = %s\n", vol_flags_to_string(v.attach_flags)); printf("\tnWaiters = %d\n", v.nWaiters); printf("\tchainCacheCheck = %d\n", v.chainCacheCheck); /* online salvage structure */ printf("\tsalvage = {\n"); printf("\t\tprio = %u\n", v.salvage.prio); printf("\t\treason = %d\n", v.salvage.reason); printf("\t\trequested = %d\n", v.salvage.requested); printf("\t\tscheduled = %d\n", v.salvage.scheduled); printf("\t}\n"); /* statistics structure */ printf("\tstats = {\n"); printf("\t\thash_lookups = {\n"); SplitInt64(v.stats.hash_lookups,hi,lo); printf("\t\t\thi = %u\n", hi); printf("\t\t\tlo = %u\n", lo); printf("\t\t}\n"); printf("\t\thash_short_circuits = {\n"); SplitInt64(v.stats.hash_short_circuits,hi,lo); printf("\t\t\thi = %u\n", hi); printf("\t\t\tlo = %u\n", lo); printf("\t\t}\n"); printf("\t\thdr_loads = {\n"); SplitInt64(v.stats.hdr_loads,hi,lo); printf("\t\t\thi = %u\n", hi); printf("\t\t\tlo = %u\n", lo); printf("\t\t}\n"); printf("\t\thdr_gets = {\n"); SplitInt64(v.stats.hdr_gets,hi,lo); printf("\t\t\thi = %u\n", hi); printf("\t\t\tlo = %u\n", lo); printf("\t\t}\n"); printf("\t\tattaches = %u\n", v.stats.attaches); printf("\t\tsoft_detaches = %u\n", v.stats.soft_detaches); printf("\t\tsalvages = %u\n", v.stats.salvages); printf("\t\tvol_ops = %u\n", v.stats.vol_ops); printf("\t\tlast_attach = %u\n", v.stats.last_attach); printf("\t\tlast_get = %u\n", v.stats.last_get); printf("\t\tlast_promote = %u\n", v.stats.last_promote); printf("\t\tlast_hdr_get = %u\n", v.stats.last_hdr_get); printf("\t\tlast_hdr_load = %u\n", v.stats.last_hdr_load); printf("\t\tlast_salvage = %u\n", v.stats.last_salvage); printf("\t\tlast_salvage_req = %u\n", v.stats.last_salvage_req); printf("\t\tlast_vol_op = %u\n", v.stats.last_vol_op); printf("\t}\n"); /* VLRU state */ printf("\tvlru = {\n"); printf("\t\tidx = %d (%s)\n", v.vlru.idx, vlru_idx_to_string(v.vlru.idx)); printf("\t}\n"); /* volume op state */ printf("\tpending_vol_op = 0x%x\n", v.pending_vol_op); } #else /* !AFS_DEMAND_ATTACH_FS */ if (res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS) { printf("*** server asserted demand attach extensions. fssync-debug not built to\n"); printf("*** recognize those extensions. please recompile fssync-debug if you need\n"); printf("*** to dump dafs extended state\n"); } #endif /* !AFS_DEMAND_ATTACH_FS */ printf("}\n"); } return 0; }
static int StatsQuery(struct cmd_syndesc * as, void * rock) { afs_int32 code; int command; struct cmd_item *ti; struct state state; SYNC_PROTO_BUF_DECL(res_buf); SYNC_response res; FSSYNC_StatsOp_hdr scom; union { void * ptr; struct VolPkgStats * vol_stats; struct VolumeHashChainStats * hash_stats; #ifdef AFS_DEMAND_ATTACH_FS struct volume_hdr_LRU_stats * hdr_stats; #endif struct DiskPartitionStats64 * vicep_stats; } sres; sres.ptr = res_buf; res.hdr.response_len = sizeof(res.hdr); res.payload.buf = res_buf; res.payload.len = SYNC_PROTO_MAX_LEN; if ((ti = as->parms[CUSTOM_PARMS_OFFSET].items)) { /* -subcommand */ if (!strcasecmp(ti->data, "vicep")) { command = FSYNC_VOL_STATS_VICEP; } else if (!strcasecmp(ti->data, "hash")) { command = FSYNC_VOL_STATS_HASH; #ifdef AFS_DEMAND_ATTACH_FS } else if (!strcasecmp(ti->data, "hdr")) { command = FSYNC_VOL_STATS_HDR; } else if (!strcasecmp(ti->data, "vlru")) { command = FSYNC_VOL_STATS_VLRU; #endif } else if (!strcasecmp(ti->data, "pkg")) { command = FSYNC_VOL_STATS_GENERAL; } else if (!strcasecmp(ti->data, "help")) { fprintf(stderr, "fssync-debug stats subcommands:\n"); fprintf(stderr, "\tpkg\tgeneral volume package stats\n"); fprintf(stderr, "\tvicep\tvice partition stats\n"); fprintf(stderr, "\thash\tvolume hash chain stats\n"); #ifdef AFS_DEMAND_ATTACH_FS fprintf(stderr, "\thdr\tvolume header cache stats\n"); fprintf(stderr, "\tvlru\tvlru generation stats\n"); #endif exit(0); } else { fprintf(stderr, "invalid stats subcommand"); exit(1); } } else { command = FSYNC_VOL_STATS_GENERAL; } if ((ti = as->parms[CUSTOM_PARMS_OFFSET+1].items)) { /* -arg1 */ switch (command) { case FSYNC_VOL_STATS_VICEP: strlcpy(scom.args.partName, ti->data, sizeof(state.vop->partName)); break; case FSYNC_VOL_STATS_HASH: scom.args.hash_bucket = atoi(ti->data); break; case FSYNC_VOL_STATS_VLRU: scom.args.vlru_generation = atoi(ti->data); break; default: fprintf(stderr, "unrecognized arguments\n"); exit(1); } } else { switch (command) { case FSYNC_VOL_STATS_VICEP: case FSYNC_VOL_STATS_HASH: case FSYNC_VOL_STATS_VLRU: fprintf(stderr, "this subcommand requires more parameters\n"); exit(1); } } common_prolog(as, &state); fprintf(stderr, "calling FSYNC_askfs with command code %d (%s)\n", command, command_code_to_string(command)); code = FSYNC_StatsOp(&scom, command, FSYNC_WHATEVER, &res); switch (code) { case SYNC_OK: case SYNC_DENIED: break; default: fprintf(stderr, "possible sync protocol error. return code was %d\n", code); } fprintf(stderr, "FSYNC_VolOp returned %d (%s)\n", code, response_code_to_string(code)); fprintf(stderr, "protocol response code was %d (%s)\n", res.hdr.response, response_code_to_string(res.hdr.response)); fprintf(stderr, "protocol reason code was %d (%s)\n", res.hdr.reason, reason_code_to_string(res.hdr.reason)); VDisconnectFS(); if (res.hdr.response == SYNC_OK) { switch (command) { case FSYNC_VOL_STATS_GENERAL: print_vol_stats_general(sres.vol_stats); break; case FSYNC_VOL_STATS_VICEP: print_vol_stats_viceP(sres.vicep_stats); break; case FSYNC_VOL_STATS_HASH: print_vol_stats_hash(sres.hash_stats); break; #ifdef AFS_DEMAND_ATTACH_FS case FSYNC_VOL_STATS_HDR: print_vol_stats_hdr(sres.hdr_stats); break; #endif /* AFS_DEMAND_ATTACH_FS */ } } return 0; }
/** * receive a command structure off a sync socket. * * @param[in] state pointer to server-side state object * @param[in] fd file descriptor on which to perform i/o * @param[out] com sync command object to be populated * * @return operation status * @retval SYNC_OK command received * @retval SYNC_COM_ERROR there was a socket communications error */ afs_int32 SYNC_getCom(SYNC_server_state_t * state, int fd, SYNC_command * com) { int n; afs_int32 code = SYNC_OK; #ifdef AFS_NT40_ENV SYNC_PROTO_BUF_DECL(buf); #else struct iovec iov[2]; int iovcnt; #endif #ifdef AFS_NT40_ENV n = recv(fd, buf, SYNC_PROTO_MAX_LEN, 0); if (n == 0 || (n < 0 && WSAEINTR != WSAGetLastError())) { Log("SYNC_getCom: error receiving command\n"); code = SYNC_COM_ERROR; goto done; } #else /* !AFS_NT40_ENV */ iov[0].iov_base = (char *)&com->hdr; iov[0].iov_len = sizeof(com->hdr); if (com->payload.len) { iov[1].iov_base = (char *)com->payload.buf; iov[1].iov_len = com->payload.len; iovcnt = 2; } else { iovcnt = 1; } n = readv(fd, iov, iovcnt); if (n == 0 || (n < 0 && errno != EINTR)) { Log("SYNC_getCom: error receiving command\n"); code = SYNC_COM_ERROR; goto done; } #endif /* !AFS_NT40_ENV */ com->recv_len = n; if (n < sizeof(com->hdr)) { Log("SYNC_getCom: command too short\n"); code = SYNC_COM_ERROR; goto done; } #ifdef AFS_NT40_ENV memcpy(&com->hdr, buf, sizeof(com->hdr)); #endif if ((n - sizeof(com->hdr)) > com->payload.len) { Log("SYNC_getCom: command too long\n"); code = SYNC_COM_ERROR; goto done; } #ifdef AFS_NT40_ENV memcpy(com->payload.buf, buf + sizeof(com->hdr), n - sizeof(com->hdr)); #endif done: return code; }
/** * send a command to a sync server and wait for a response. * * @param[in] state pointer to sync client handle * @param[in] com command object * @param[out] res response object * * @return operation status * @retval SYNC_OK success * @retval SYNC_COM_ERROR communications error * * @internal */ static afs_int32 SYNC_ask_internal(SYNC_client_state * state, SYNC_command * com, SYNC_response * res) { int n; SYNC_PROTO_BUF_DECL(buf); #ifndef AFS_NT40_ENV int iovcnt; struct iovec iov[2]; #endif if (state->fd == -1) { Log("SYNC_ask: invalid sync file descriptor on circuit '%s'\n", state->proto_name); res->hdr.response = SYNC_COM_ERROR; goto done; } if (com->hdr.command_len > SYNC_PROTO_MAX_LEN) { Log("SYNC_ask: internal SYNC buffer too small on circuit '%s'; " "please file a bug\n", state->proto_name); res->hdr.response = SYNC_COM_ERROR; goto done; } /* * fill in some common header fields */ com->hdr.proto_version = state->proto_version; com->hdr.pkt_seq = ++state->pkt_seq; com->hdr.com_seq = ++state->com_seq; #ifdef AFS_NT40_ENV com->hdr.pid = 0; com->hdr.tid = 0; #else com->hdr.pid = getpid(); #ifdef AFS_PTHREAD_ENV com->hdr.tid = (afs_int32)pthread_self(); #else { PROCESS handle = LWP_ThreadId(); com->hdr.tid = (handle) ? handle->index : 0; } #endif /* !AFS_PTHREAD_ENV */ #endif /* !AFS_NT40_ENV */ memcpy(buf, &com->hdr, sizeof(com->hdr)); if (com->payload.len) { memcpy(buf + sizeof(com->hdr), com->payload.buf, com->hdr.command_len - sizeof(com->hdr)); } #ifdef AFS_NT40_ENV n = send(state->fd, buf, com->hdr.command_len, 0); if (n != com->hdr.command_len) { Log("SYNC_ask: write failed on circuit '%s'\n", state->proto_name); res->hdr.response = SYNC_COM_ERROR; goto done; } if (com->hdr.command == SYNC_COM_CHANNEL_CLOSE) { /* short circuit close channel requests */ res->hdr.response = SYNC_OK; goto done; } n = recv(state->fd, buf, SYNC_PROTO_MAX_LEN, 0); if (n == 0 || (n < 0 && WSAEINTR != WSAGetLastError())) { Log("SYNC_ask: No response on circuit '%s'\n", state->proto_name); res->hdr.response = SYNC_COM_ERROR; goto done; } #else /* !AFS_NT40_ENV */ n = write(state->fd, buf, com->hdr.command_len); if (com->hdr.command_len != n) { Log("SYNC_ask: write failed on circuit '%s'\n", state->proto_name); res->hdr.response = SYNC_COM_ERROR; goto done; } if (com->hdr.command == SYNC_COM_CHANNEL_CLOSE) { /* short circuit close channel requests */ res->hdr.response = SYNC_OK; goto done; } /* receive the response */ iov[0].iov_base = (char *)&res->hdr; iov[0].iov_len = sizeof(res->hdr); if (res->payload.len) { iov[1].iov_base = (char *)res->payload.buf; iov[1].iov_len = res->payload.len; iovcnt = 2; } else { iovcnt = 1; } n = readv(state->fd, iov, iovcnt); if (n == 0 || (n < 0 && errno != EINTR)) { Log("SYNC_ask: No response on circuit '%s'\n", state->proto_name); res->hdr.response = SYNC_COM_ERROR; goto done; } #endif /* !AFS_NT40_ENV */ res->recv_len = n; if (n < sizeof(res->hdr)) { Log("SYNC_ask: response too short on circuit '%s'\n", state->proto_name); res->hdr.response = SYNC_COM_ERROR; goto done; } #ifdef AFS_NT40_ENV memcpy(&res->hdr, buf, sizeof(res->hdr)); #endif if ((n - sizeof(res->hdr)) > res->payload.len) { Log("SYNC_ask: response too long on circuit '%s'\n", state->proto_name); res->hdr.response = SYNC_COM_ERROR; goto done; } #ifdef AFS_NT40_ENV memcpy(res->payload.buf, buf + sizeof(res->hdr), n - sizeof(res->hdr)); #endif if (res->hdr.response_len != n) { Log("SYNC_ask: length field in response inconsistent " "on circuit '%s'\n", state->proto_name); res->hdr.response = SYNC_COM_ERROR; goto done; } if (res->hdr.response == SYNC_DENIED) { Log("SYNC_ask: negative response on circuit '%s'\n", state->proto_name); } done: return res->hdr.response; }