ypxfr.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,787 行 · 第 1/3 页
C
1,787 行
}/* * This gets values for the YP_LAST_MODIFIED and YP_MASTER_NAME keys from the * master server's version of the map. Values are held in static variables * here. In the success cases, global pointer variables are set to point at * the local statics. */boolget_private_recs(pushstat) int *pushstat;{ static char anumber[20]; static unsigned number; static char name[YPMAXPEER + 1]; int status; status = 0; if (get_order(anumber, &number, &status) ) { master_version = &number; master_ascii_version = anumber; } else { if (status != 0) { *pushstat = status; return (FALSE); } } if (get_master_name(name, &status) ) { master_name = name; } else { if (status != 0) { *pushstat = status; return (FALSE); } master_name = master; } return (TRUE);}/* * This gets the map's order number from the master server */boolget_order(an, n, pushstat) char *an; unsigned *n; int *pushstat;{ if (master_prog_vers == YPVERS) { return (get_v2order(an, n, pushstat) ); } else { return (get_v1order(an, n, pushstat) ); }}boolget_v1order(an, n, pushstat) char *an; unsigned *n; int *pushstat;{ struct yprequest req; struct ypresponse resp; bool retval; char errmsg[256]; retval = FALSE; req.yp_reqtype = YPMATCH_REQTYPE; req.ypmatch_req_domain = domain; req.ypmatch_req_map = map; req.ypmatch_req_keyptr = yp_last_modified; req.ypmatch_req_keysize = (sizeof (yp_last_modified)) - 1; resp.ypmatch_resp_valptr = NULL; resp.ypmatch_resp_valsize = 0; if(clnt_call(master_server.dom_client, YPOLDPROC_MATCH, _xdr_yprequest, &req, _xdr_ypresponse, &resp, udp_timeout) == RPC_SUCCESS) { if (resp.ypmatch_resp_status == YP_TRUE) { bcopy(resp.ypmatch_resp_valptr, an, resp.ypmatch_resp_valsize); an[resp.ypmatch_resp_valsize] = '\0'; *n = atoi(an); retval = TRUE; } else if (resp.ypmatch_resp_status != YP_NOKEY) { *pushstat = map_yperr_to_pusherr( resp.ypmatch_resp_status); if (!logging) { logprintf( "(info) Can't get order number from ypserv at %s. Reason: %s.\n", master, yperr_string(ypprot_err( (unsigned) resp.ypmatch_resp_status)) ); } } CLNT_FREERES(master_server.dom_client, _xdr_ypresponse, &resp); } else { *pushstat = YPPUSH_RPC; (void) sprintf(errmsg, "ypxfr(get_v1order) RPC call to %s failed", master); clnt_perror(master_server.dom_client, errmsg); } return(retval);}boolget_v2order(an, n, pushstat) char *an; unsigned *n; int *pushstat;{ struct ypreq_nokey req; struct ypresp_order resp; int retval; char errmsg[256]; req.domain = domain; req.map = map; /* * Get the map''s order number, null-terminate it and store it, * and convert it to binary and store it again. */ retval = FALSE; if((enum clnt_stat) clnt_call(master_server.dom_client, YPPROC_ORDER, xdr_ypreq_nokey, &req, xdr_ypresp_order, &resp, udp_timeout) == RPC_SUCCESS) { if (resp.status == YP_TRUE) { sprintf(an, "%d", resp.ordernum); *n = resp.ordernum; retval = TRUE; } else if (resp.status != YP_BADDB) { *pushstat = ypprot_err(resp.status); if (!logging) { logprintf( "(info) Can't get order number from ypserv at %s. Reason: %s.\n", master, yperr_string( ypprot_err(resp.status)) ); } } CLNT_FREERES(master_server.dom_client, xdr_ypresp_order, &resp); } else { *pushstat = YPPUSH_RPC; logprintf("ypxfr(get_v2order) RPC call to %s failed", master); clnt_perror(master_server.dom_client, ""); } return (retval);}/* * This gets the map's master name from the master server */boolget_master_name(name, pushstat) char *name; int *pushstat;{ if (master_prog_vers == YPVERS) { return (get_v2master_name(name, pushstat)); } else { return (get_v1master_name(name, pushstat)); }}boolget_v1master_name(name, pushstat) char *name; int *pushstat;{ struct yprequest req; struct ypresponse resp; bool retval; char errmsg[256]; retval = FALSE; req.yp_reqtype = YPMATCH_REQTYPE; req.ypmatch_req_domain = domain; req.ypmatch_req_map = map; req.ypmatch_req_keyptr = yp_master_name; req.ypmatch_req_keysize = (sizeof (yp_master_name)) -1; resp.ypmatch_resp_valptr = NULL; resp.ypmatch_resp_valsize = 0; if(clnt_call(master_server.dom_client, YPOLDPROC_MATCH, _xdr_yprequest, &req, _xdr_ypresponse, &resp, udp_timeout) == RPC_SUCCESS) { if (resp.ypmatch_resp_status == YP_TRUE) { bcopy(resp.ypmatch_resp_valptr, name, resp.ypmatch_resp_valsize); name[resp.ypmatch_resp_valsize] = '\0'; retval = TRUE; } else if (resp.ypmatch_resp_status != YP_NOKEY) { *pushstat = map_yperr_to_pusherr( resp.ypmatch_resp_status); logprintf( "(info) Can't get master name from ypserv at %s. Reason: %s.\n", master, yperr_string(ypprot_err((unsigned) resp.ypmatch_resp_status)) ); } CLNT_FREERES(master_server.dom_client, _xdr_ypresponse, &resp); } else { *pushstat = YPPUSH_RPC; (void) sprintf(errmsg, "ypxfr(get_v1master_name) RPC call to %s failed", master); clnt_perror(master_server.dom_client, errmsg); } return(retval);}boolget_v2master_name(name, pushstat) char *name; int *pushstat;{ struct ypreq_nokey req; struct ypresp_master resp; int retval; char errmsg[256]; req.domain = domain; req.map = map; resp.master = NULL; retval = FALSE; if((enum clnt_stat) clnt_call(master_server.dom_client, YPPROC_MASTER, xdr_ypreq_nokey, &req, xdr_ypresp_master, &resp, udp_timeout) == RPC_SUCCESS) { if (resp.status == YP_TRUE) { strcpy(name, resp.master); retval = TRUE; } else if (resp.status != YP_BADDB) { *pushstat = ypprot_err(resp.status); if (!logging) { logprintf("(info) Can't get master name from ypserv at %s. Reason: %s.\n", master, yperr_string( ypprot_err(resp.status)) ); } } CLNT_FREERES(master_server.dom_client, xdr_ypresp_master, &resp); } else { *pushstat = YPPUSH_RPC; logprintf( "ypxfr(get_v2master_name) RPC call to %s failed", master); clnt_perror(master_server.dom_client, ""); } return (retval);}/* * This tries to get the master name for the named map, from any * server's version, using the vanilla yp client interface. If we get a * name back, the global "master" gets pointed to it. */voidfind_map_master(){ int err; if (err = yp_master(domain, map, &master)) { logprintf("Can't get master of %s. Reason: %s.\n", map, yperr_string(err)); } yp_unbind(domain);}/* * This does the work of transferrring the map. */boolmove_map(pushstat) int *pushstat;{ unsigned local_version; char map_name[MAXNAMLEN + 1]; char tmp_name[MAXNAMLEN + 1]; char bkup_name[MAXNAMLEN + 1]; char an[11]; unsigned n; mkfilename(map_name); if (!force) { local_version = get_local_version(map_name); if (local_version >= *master_version) { logprintf( "Map %s at %s is not more recent than local.\n", map, master); *pushstat = YPPUSH_AGE; return (FALSE); } } mk_tmpname(yptempname_prefix, tmp_name); if (!new_mapfiles(tmp_name) ) { logprintf( "Can't create temp map %s.\n", tmp_name); *pushstat = YPPUSH_FILE; return (FALSE); } if (dbminit(tmp_name) < 0) { logprintf( "Can't dbm init temp map %s.\n", tmp_name); del_mapfiles(tmp_name); *pushstat = YPPUSH_DBM; return (FALSE); } if (!get_map(tmp_name, pushstat) ) { del_mapfiles(tmp_name); return (FALSE); } if (!add_private_entries(tmp_name) ) { del_mapfiles(tmp_name); *pushstat = YPPUSH_DBM; return (FALSE); } if (dbmclose(tmp_name) < 0) { logprintf( "Can't do dbm close operation on temp map %s.\n", tmp_name); del_mapfiles(tmp_name); *pushstat = YPPUSH_DBM; return (FALSE); } if (!get_order(an, &n, pushstat)) { return(FALSE); } if (n != *master_version) { logprintf( "Version skew at %s while transferring map %s.\n", master, map); del_mapfiles(tmp_name); *pushstat = YPPUSH_SKEW; return (FALSE); }# ifdef PARANOID if (!count_mismatch(tmp_name,entry_count)) { del_mapfiles(tmp_name); *pushstat = YPPUSH_DBM; return(FALSE); }# endif PARANOID if (!check_map_existence(map_name) ) { if (!rename_map(tmp_name, map_name) ) { del_mapfiles(tmp_name); logprintf( "Rename error: couldn't mv %s to %s.\n", tmp_name, map_name); *pushstat = YPPUSH_FILE; return (FALSE); } } else { mk_tmpname(ypbkupname_prefix, bkup_name); if (!rename_map(map_name, bkup_name) ) { (void) rename_map(bkup_name, map_name); logprintf( "Rename error: check that old %s is still intact.\n", map_name); del_mapfiles(tmp_name); *pushstat = YPPUSH_FILE; return (FALSE); } if (rename_map(tmp_name, map_name) ) { del_mapfiles(bkup_name); } else { del_mapfiles(tmp_name); (void) rename_map(bkup_name, map_name); logprintf( "Rename error: check that old %s is still intact.\n", map_name); *pushstat = YPPUSH_FILE; return (FALSE); } } return (TRUE);}/* * This tries to get the order number out of the local version of the map. * If the attempt fails for any version, the function will return "0" */unsignedget_local_version(name) char *name;{ datum key; datum val; char number[11]; if (!check_map_existence(name) ) { return (0); } if (dbminit(name) < 0) { return (0); } key.dptr = yp_last_modified; key.dsize = (sizeof (yp_last_modified) - 1); val = fetch(key); (void) dbmclose(name); if (!val.dptr) { return (0); } if (val.dsize == 0 || val.dsize > 10) { return (0); } (void) bcopy(val.dptr, number, val.dsize); number[val.dsize] = '\0'; return ((unsigned) atoi(number) );}/* * This constructs a file name for a map, minus its ".dir" or ".pag" extensions */voidmkfilename(ppath) char *ppath;{ if ( (strlen(domain) + strlen(map) + strlen(ypdbpath) + 3) > (MAXNAMLEN + 1) ) { logprintf( "Map name string too long.\n"); } (void) strcpy(ppath, ypdbpath); (void) strcat(ppath, "/"); (void) strcat(ppath, domain); (void) strcat(ppath, "/"); (void) strcat(ppath, map);}/* * This returns a temporary name for a map transfer minus its ".dir" or * ".pag" extensions. */voidmk_tmpname(prefix, xfr_name) char *prefix; char *xfr_name;{ char xfr_anumber[10]; long xfr_number; if (!xfr_name) { return; } xfr_number = getpid(); (void) sprintf(xfr_anumber, "%d", xfr_number); (void) strcpy(xfr_name, ypdbpath); (void) strcat(xfr_name, "/"); (void) strcat(xfr_name, domain); (void) strcat(xfr_name, "/"); (void) strcat(xfr_name, prefix); (void) strcat(xfr_name, map); (void) strcat(xfr_name, "."); (void) strcat(xfr_name, xfr_anumber);}/* * This deletes the .pag and .dir files which implement a map. * * Note: No error checking is done here for a garbage input file name or for * failed unlink operations. */voiddel_mapfiles(basename) char *basename;{ char dbfilename[MAXNAMLEN + 1]; if (!basename) { return; } strcpy(dbfilename, basename); strcat(dbfilename, ".pag"); unlink(dbfilename); strcpy(dbfilename, basename); strcat(dbfilename, ".dir"); unlink(dbfilename);}/* * This checks to see if the source map files exist, then renames them to the * target names. This is a boolean function. The file names from.pag and * from.dir will be changed to to.pag and to.dir in the success case. * * Note: If the second of the two renames fails, yprename_map will try to * un-rename the first pair, and leave the world in the state it was on entry. * This might fail, too, though... */boolrename_map(from, to) char *from; char *to;{ char fromfile[MAXNAMLEN + 1]; char tofile[MAXNAMLEN + 1]; char savefile[MAXNAMLEN + 1]; if (!from || !to) { return (FALSE); } if (!check_map_existence(from) ) { return (FALSE); } (void) strcpy(fromfile, from); (void) strcat(fromfile, ".pag"); (void) strcpy(tofile, to); (void) strcat(tofile, ".pag"); if (rename(fromfile, tofile) ) { logprintf( "Can't mv %s to %s.\n", fromfile, tofile); return (FALSE); } (void) strcpy(fromfile, from); (void) strcat(fromfile, ".dir"); (void) strcpy(tofile, to); (void) strcat(tofile, ".dir"); if (rename(fromfile, tofile) ) { logprintf( "Can't mv %s to %s.\n", fromfile, tofile); (void) strcpy(fromfile, from); (void) strcat(fromfile, ".pag"); (void) strcpy(tofile, to); (void) strcat(tofile, ".pag"); if (rename(tofile, fromfile) ) { logprintf( "Can't recover from rename failure.\n"); return (FALSE); } return (FALSE); } return (TRUE);}/* * This performs an existence check on the dbm data base files <pname>.pag and * <pname>.dir. */boolcheck_map_existence(pname) char *pname;{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?