void jnl_prc_vector (jnl_process_vector *pv) { unsigned char *c, *s; struct passwd *pw; uid_t eff_uid; /* try to see why gets pwuid == nil */ int gethostname_res; time_t temp_time; memset(pv, 0, sizeof(jnl_process_vector)); pv->jpv_pid = process_id; time(&temp_time); pv->jpv_time = temp_time; GETHOSTNAME(pv->jpv_node, JPV_LEN_NODE, gethostname_res); eff_uid = geteuid(); /* save results of each step */ errno = 0; /* force to known value per man page */ GETPWUID(eff_uid, pw); if (pw) { strncpy(pv->jpv_user, pw->pw_name, JPV_LEN_USER); strncpy(pv->jpv_prcnam, pw->pw_name, JPV_LEN_PRCNAM); } else { #ifdef SMW FPRINTF(stderr,"\n?DEBUG - jnl_prc_vector: pw = (nil), euid = %d, pid = %d, errno = %d\n", eff_uid, process_id, errno); #endif #ifdef DEBUG strncpy(pv->jpv_user,"ERROR=",JPV_LEN_USER); if (errno < 1000) /* protect against overflow */ c = i2asc((uchar_ptr_t)pv->jpv_user + 6, errno); /* past = above */ #endif } endpwent(); /* close passwd file to free channel */ if ((c = (unsigned char *)TTYNAME(0)) != NULL) { /* Get basename for tty */ for (s = c + strlen((char*)c); s > c; --s) if (*s == '/') { ++s; break; } strncpy(pv->jpv_terminal, (char *)s, JPV_LEN_TERMINAL); } }
void armci_init_clusinfo() { char name[MAX_HOSTNAME], *merged; int len, limit, rc; char *tmp; char *enval; if((tmp =getenv("ARMCI_HOSTNAME")) == NULL){ limit = MAX_HOSTNAME-1; rc = GETHOSTNAME(name, limit); if(rc < 0)armci_die("armci: gethostname failed",rc); tmp = new_hostname(name); } if(tmp != NULL){ if(strlen(tmp) >= MAX_HOSTNAME) armci_die("armci: hostname too long",strlen(tmp)); strcpy(name,tmp); printf("%d using %s hostname\n",armci_me, name); fflush(stdout); } len = strlen(name); #ifdef ARMCI_ENABLE_GPC_CALLS /*a simple way to run as many servers as compute processes*/ enval = getenv("ARMCI_NSERV_EQ_NPROC"); if(enval != NULL){ sprintf(name+len,"n%d",getpid()); len = strlen(name); printf("\n%s\n",name); } #endif #ifdef HOSTNAME_TRUNCATE { /* in some cases (e.g.,SP) when name is used to determine * cluster structure but not to establish communication * we can truncate hostnames to save memory */ int i; limit = HOSTNAME_LEN-1; for(i=0; i<len; i++){ if(name[i] =='.')break; /*we are not truncating 1st part of hostname*/ if(i==limit)armci_die("Please increase HOSTNAME_LEN in ARMCI >",i+1); } if(len>limit)name[limit]='\0'; len =limit; } #else if(len >= HOSTNAME_LEN-1) armci_die("armci: gethostname overrun name string length",len); #endif #ifdef NO_SHMEM if(armci_enable_alpha_hack()) { name[len]='0'+armci_me; name[len+1]='\0'; len++; } #endif if(DEBUG) fprintf(stderr,"%d: %s len=%d\n",armci_me, name,(int)strlen(name)); #ifdef CLUSTER merged = merge_names(name); /* create hostname list */ process_hostlist(merged); /* compute cluster info */ free(merged); #else process_hostlist(name); /* compute cluster info */ #endif armci_master = armci_clus_info[armci_clus_me].master; #ifdef NO_SHMEM if(armci_enable_alpha_hack()) { int i; for(i=0;i<armci_nclus;i++){ int len=strlen(armci_clus_info[i].hostname); /* fprintf(stderr,"----hostlen=%d\n",len);*/ armci_clus_info[i].hostname[len-1]='\0'; } } #endif print_clus_info(); }
void db_init(gd_region *reg, sgmnt_data_ptr_t tsd) { static boolean_t mutex_init_done = FALSE; boolean_t is_bg, read_only; char machine_name[MAX_MCNAMELEN]; file_control *fc; int gethostname_res, stat_res, mm_prot; int4 status, semval, dblksize, fbwsize; sm_long_t status_l; sgmnt_addrs *csa; sgmnt_data_ptr_t csd; struct sembuf sop[3]; struct stat stat_buf; union semun semarg; struct semid_ds semstat; struct shmid_ds shmstat; struct statvfs dbvfs; uint4 sopcnt; unix_db_info *udi; #ifdef periodic_timer_removed void periodic_flush_check(); #endif error_def(ERR_CLSTCONFLICT); error_def(ERR_CRITSEMFAIL); error_def(ERR_DBNAMEMISMATCH); error_def(ERR_DBIDMISMATCH); error_def(ERR_NLMISMATCHCALC); error_def(ERR_REQRUNDOWN); error_def(ERR_SYSCALL); assert(tsd->acc_meth == dba_bg || tsd->acc_meth == dba_mm); is_bg = (dba_bg == tsd->acc_meth); read_only = reg->read_only; new_dbinit_ipc = FALSE; /* we did not create a new ipc resource */ udi = FILE_INFO(reg); memset(machine_name, 0, sizeof(machine_name)); if (GETHOSTNAME(machine_name, MAX_MCNAMELEN, gethostname_res)) rts_error(VARLSTCNT(5) ERR_TEXT, 2, LEN_AND_LIT("Unable to get the hostname"), errno); assert(strlen(machine_name) < MAX_MCNAMELEN); csa = &udi->s_addrs; csa->db_addrs[0] = csa->db_addrs[1] = csa->lock_addrs[0] = NULL; /* to help in dbinit_ch and gds_rundown */ reg->opening = TRUE; /* * Create ftok semaphore for this region. * We do not want to make ftok counter semaphore to be 2 for on mupip journal recover process. */ if (!ftok_sem_get(reg, !mupip_jnl_recover, GTM_ID, FALSE)) rts_error(VARLSTCNT(4) ERR_DBFILERR, 2, DB_LEN_STR(reg)); /* * At this point we have ftok_semid sempahore based on ftok key. * Any ftok conflicted region will block at this point. * Say, a.dat and b.dat both has same ftok and we have process A to access a.dat and * process B to access b.dat. In this case only one can continue to do db_init() */ fc = reg->dyn.addr->file_cntl; fc->file_type = reg->dyn.addr->acc_meth; fc->op = FC_READ; fc->op_buff = (sm_uc_ptr_t)tsd; fc->op_len = sizeof(*tsd); fc->op_pos = 1; dbfilop(fc); /* Read file header */ udi->shmid = tsd->shmid; udi->semid = tsd->semid; udi->sem_ctime = tsd->sem_ctime.ctime; udi->shm_ctime = tsd->shm_ctime.ctime; dbsecspc(reg, tsd); /* Find db segment size */ if (!mupip_jnl_recover) { if (INVALID_SEMID == udi->semid) { if (0 != udi->sem_ctime || INVALID_SHMID != udi->shmid || 0 != udi->shm_ctime) /* We must have somthing wrong in protocol or, code, if this happens */ GTMASSERT; /* * Create new semaphore using IPC_PRIVATE. System guarantees a unique id. */ if (-1 == (udi->semid = semget(IPC_PRIVATE, FTOK_SEM_PER_ID, RWDALL | IPC_CREAT))) { udi->semid = INVALID_SEMID; rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, LEN_AND_LIT("Error with database control semget"), errno); } udi->shmid = INVALID_SHMID; /* reset shmid so dbinit_ch does not get confused in case we go there */ new_dbinit_ipc = TRUE; tsd->semid = udi->semid; semarg.val = GTM_ID; /* * Following will set semaphore number 2 (=FTOK_SEM_PER_ID - 1) value as GTM_ID. * In case we have orphaned semaphore for some reason, mupip rundown will be * able to identify GTM semaphores from the value and can remove. */ if (-1 == semctl(udi->semid, FTOK_SEM_PER_ID - 1, SETVAL, semarg)) rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, LEN_AND_LIT("Error with database control semctl SETVAL"), errno); /* * Warning: We must read the sem_ctime using IPC_STAT after SETVAL, which changes it. * We must NOT do any more SETVAL after this. Our design is to use * sem_ctime as creation time of semaphore. */ semarg.buf = &semstat; if (-1 == semctl(udi->semid, FTOK_SEM_PER_ID - 1, IPC_STAT, semarg)) rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, LEN_AND_LIT("Error with database control semctl IPC_STAT"), errno); tsd->sem_ctime.ctime = udi->sem_ctime = semarg.buf->sem_ctime; } else { if (INVALID_SHMID == udi->shmid) /* if mu_rndwn_file gets standalone access of this region and * somehow mupip process crashes, we can have semid != -1 but shmid == -1 */ rts_error(VARLSTCNT(10) ERR_REQRUNDOWN, 4, DB_LEN_STR(reg), LEN_AND_STR(tsd->machine_name), ERR_TEXT, 2, LEN_AND_LIT("semid is valid but shmid is invalid")); semarg.buf = &semstat; if (-1 == semctl(udi->semid, 0, IPC_STAT, semarg)) /* file header has valid semid but semaphore does not exists */ rts_error(VARLSTCNT(6) ERR_REQRUNDOWN, 4, DB_LEN_STR(reg), LEN_AND_STR(tsd->machine_name)); else if (semarg.buf->sem_ctime != tsd->sem_ctime.ctime) rts_error(VARLSTCNT(10) ERR_REQRUNDOWN, 4, DB_LEN_STR(reg), LEN_AND_STR(tsd->machine_name), ERR_TEXT, 2, LEN_AND_LIT("sem_ctime does not match")); if (-1 == shmctl(udi->shmid, IPC_STAT, &shmstat)) rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, LEN_AND_LIT("Error with database control shmctl"), errno); else if (shmstat.shm_ctime != tsd->shm_ctime.ctime) rts_error(VARLSTCNT(10) ERR_REQRUNDOWN, 4, DB_LEN_STR(reg), LEN_AND_STR(tsd->machine_name), ERR_TEXT, 2, LEN_AND_LIT("shm_ctime does not match")); } /* We already have ftok semaphore of this region, so just plainly do semaphore operation */ /* This is the database access control semaphore for any region */ sop[0].sem_num = 0; sop[0].sem_op = 0; /* Wait for 0 */ sop[1].sem_num = 0; sop[1].sem_op = 1; /* Lock */ sopcnt = 2; if (!read_only) { sop[2].sem_num = 1; sop[2].sem_op = 1; /* increment r/w access counter */ sopcnt = 3; } sop[0].sem_flg = sop[1].sem_flg = sop[2].sem_flg = SEM_UNDO | IPC_NOWAIT; SEMOP(udi->semid, sop, sopcnt, status); if (-1 == status) { errno_save = errno; gtm_putmsg(VARLSTCNT(4) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg)); rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("semop()"), CALLFROM, errno_save); } } else /* for mupip_jnl_recover we were already in mu_rndwn_file and got "semid" semaphore */ { if (INVALID_SEMID == udi->semid || 0 == udi->sem_ctime) /* make sure mu_rndwn_file() has reset created semaphore for standalone access */ GTMASSERT; if (INVALID_SHMID != udi->shmid || 0 != udi->shm_ctime) /* make sure mu_rndwn_file() has reset shared memory */ GTMASSERT; udi->shmid = INVALID_SHMID; /* reset shmid so dbinit_ch does not get confused in case we go there */ new_dbinit_ipc = TRUE; } sem_incremented = TRUE; if (new_dbinit_ipc) { /* Create new shared memory using IPC_PRIVATE. System guarantees a unique id */ #ifdef __MVS__ if (-1 == (status_l = udi->shmid = shmget(IPC_PRIVATE, ROUND_UP(reg->sec_size, MEGA_BOUND), __IPC_MEGA | IPC_CREAT | RWDALL))) #else if (-1 == (status_l = udi->shmid = shmget(IPC_PRIVATE, reg->sec_size, RWDALL | IPC_CREAT))) #endif { udi->shmid = status_l = INVALID_SHMID; rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, LEN_AND_LIT("Error with database shmget"), errno); } tsd->shmid = udi->shmid; if (-1 == shmctl(udi->shmid, IPC_STAT, &shmstat)) rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, LEN_AND_LIT("Error with database control shmctl"), errno); tsd->shm_ctime.ctime = udi->shm_ctime = shmstat.shm_ctime; } #ifdef DEBUG_DB64 status_l = (sm_long_t)(csa->db_addrs[0] = (sm_uc_ptr_t)do_shmat(udi->shmid, next_smseg, SHM_RND)); next_smseg = (sm_uc_ptr_t)ROUND_UP((sm_long_t)(next_smseg + reg->sec_size), SHMAT_ADDR_INCS); #else status_l = (sm_long_t)(csa->db_addrs[0] = (sm_uc_ptr_t)do_shmat(udi->shmid, 0, SHM_RND)); #endif if (-1 == status_l) { rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, LEN_AND_LIT("Error attaching to database shared memory"), errno); } csa->nl = (node_local_ptr_t)csa->db_addrs[0]; csa->critical = (mutex_struct_ptr_t)(csa->db_addrs[0] + NODE_LOCAL_SIZE); assert(((int)csa->critical & 0xf) == 0); /* critical should be 16-byte aligned */ #ifdef CACHELINE_SIZE assert(0 == ((int)csa->critical & (CACHELINE_SIZE - 1))); #endif /* Note: Here we check jnl_sate from database file and its value cannot change without standalone access. * The jnl_buff buffer should be initialized irrespective of read/write process */ JNL_INIT(csa, reg, tsd); csa->backup_buffer = (backup_buff_ptr_t)(csa->db_addrs[0] + NODE_LOCAL_SPACE + JNL_SHARE_SIZE(tsd)); csa->lock_addrs[0] = (sm_uc_ptr_t)csa->backup_buffer + BACKUP_BUFFER_SIZE + 1; csa->lock_addrs[1] = csa->lock_addrs[0] + LOCK_SPACE_SIZE(tsd) - 1; csa->total_blks = tsd->trans_hist.total_blks; /* For test to see if file has extended */ if (new_dbinit_ipc) { memset(csa->nl, 0, sizeof(*csa->nl)); /* We allocated shared storage -- we have to init it */ if (JNL_ALLOWED(csa)) { /* initialize jb->cycle to a value different from initial value of jpc->cycle (0). although this is not * necessary right now, in the future, the plan is to change jnl_ensure_open() to only do a cycle mismatch * check in order to determine whether to call jnl_file_open() or not. this is in preparation for that. */ csa->jnl->jnl_buff->cycle = 1; } } if (is_bg) csd = csa->hdr = (sgmnt_data_ptr_t)(csa->lock_addrs[1] + 1 + CACHE_CONTROL_SIZE(tsd)); else { csa->acc_meth.mm.mmblk_state = (mmblk_que_heads_ptr_t)(csa->lock_addrs[1] + 1); FSTAT_FILE(udi->fd, &stat_buf, stat_res); if (-1 == stat_res) rts_error(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), errno); mm_prot = read_only ? PROT_READ : (PROT_READ | PROT_WRITE); #ifdef DEBUG_DB64 if (-1 == (sm_long_t)(csa->db_addrs[0] = (sm_uc_ptr_t)mmap((caddr_t)get_mmseg((size_t)stat_buf.st_size), (size_t)stat_buf.st_size, mm_prot, GTM_MM_FLAGS, udi->fd, (off_t)0))) rts_error(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), errno); put_mmseg((caddr_t)(csa->db_addrs[0]), (size_t)stat_buf.st_size); #else if (-1 == (sm_long_t)(csa->db_addrs[0] = (sm_uc_ptr_t)mmap((caddr_t)NULL, (size_t)stat_buf.st_size, mm_prot, GTM_MM_FLAGS, udi->fd, (off_t)0))) rts_error(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), errno); #endif csa->db_addrs[1] = csa->db_addrs[0] + stat_buf.st_size - 1; csd = csa->hdr = (sgmnt_data_ptr_t)csa->db_addrs[0]; } if (!csa->nl->glob_sec_init) { assert(new_dbinit_ipc); if (is_bg) *csd = *tsd; if (csd->machine_name[0]) /* crash occured */ { if (0 != memcmp(csd->machine_name, machine_name, MAX_MCNAMELEN)) /* crashed on some other node */ rts_error(VARLSTCNT(6) ERR_CLSTCONFLICT, 4, DB_LEN_STR(reg), LEN_AND_STR(csd->machine_name)); else rts_error(VARLSTCNT(6) ERR_REQRUNDOWN, 4, DB_LEN_STR(reg), LEN_AND_STR(csd->machine_name)); } if (is_bg) { bt_malloc(csa); csa->nl->cache_off = -CACHE_CONTROL_SIZE(tsd); db_csh_ini(csa); } db_csh_ref(csa); strcpy(csa->nl->machine_name, machine_name); /* machine name */ assert(MAX_REL_NAME > gtm_release_name_len); memcpy(csa->nl->now_running, gtm_release_name, gtm_release_name_len + 1); /* GT.M release name */ memcpy(csa->nl->label, GDS_LABEL, GDS_LABEL_SZ - 1); /* GDS label */ memcpy(csa->nl->fname, reg->dyn.addr->fname, reg->dyn.addr->fname_len); /* database filename */ csa->nl->creation_date_time = csd->creation.date_time; csa->nl->highest_lbm_blk_changed = -1; csa->nl->wcs_timers = -1; csa->nl->nbb = BACKUP_NOT_IN_PROGRESS; csa->nl->unique_id.uid = FILE_INFO(reg)->fileid; /* save what file we initialized this storage for */ /* save pointers in csa to access shared memory */ csa->nl->critical = (sm_off_t)((sm_uc_ptr_t)csa->critical - (sm_uc_ptr_t)csa->nl); if (JNL_ALLOWED(csa)) csa->nl->jnl_buff = (sm_off_t)((sm_uc_ptr_t)csa->jnl->jnl_buff - (sm_uc_ptr_t)csa->nl); csa->nl->backup_buffer = (sm_off_t)((sm_uc_ptr_t)csa->backup_buffer - (sm_uc_ptr_t)csa->nl); csa->nl->hdr = (sm_off_t)((sm_uc_ptr_t)csd - (sm_uc_ptr_t)csa->nl); csa->nl->lock_addrs = (sm_off_t)((sm_uc_ptr_t)csa->lock_addrs[0] - (sm_uc_ptr_t)csa->nl); if (!read_only || is_bg) { csd->trans_hist.early_tn = csd->trans_hist.curr_tn; csd->max_update_array_size = csd->max_non_bm_update_array_size = ROUND_UP2(MAX_NON_BITMAP_UPDATE_ARRAY_SIZE(csd), UPDATE_ARRAY_ALIGN_SIZE); csd->max_update_array_size += ROUND_UP2(MAX_BITMAP_UPDATE_ARRAY_SIZE, UPDATE_ARRAY_ALIGN_SIZE); /* add current db_csh counters into the cumulative counters and reset the current counters */ #define TAB_DB_CSH_ACCT_REC(COUNTER, DUMMY1, DUMMY2) \ csd->COUNTER.cumul_count += csd->COUNTER.curr_count; \ csd->COUNTER.curr_count = 0; #include "tab_db_csh_acct_rec.h" #undef TAB_DB_CSH_ACCT_REC } if (!read_only) { if (is_bg) { assert(memcmp(csd, GDS_LABEL, GDS_LABEL_SZ - 1) == 0); LSEEKWRITE(udi->fd, (off_t)0, (sm_uc_ptr_t)csd, sizeof(sgmnt_data), errno_save); if (0 != errno_save) { rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, LEN_AND_LIT("Error with database write"), errno_save); } } } reg->dyn.addr->ext_blk_count = csd->extension_size; mlk_shr_init(csa->lock_addrs[0], csd->lock_space_size, csa, (FALSE == read_only)); DEBUG_ONLY(locknl = csa->nl;) /* for DEBUG_ONLY LOCK_HIST macro */
int4 parse_file(mstr *file, parse_blk *pblk) { struct stat statbuf; struct addrinfo *ai_ptr, *localhost_ai_ptr, *temp_ai_ptr, hints; mstr trans, tmp; int status, diff, local_node_len, query_node_len, node_name_len; parse_blk def; char local_node_name[MAX_HOST_NAME_LEN + 1], query_node_name[MAX_HOST_NAME_LEN + 1]; char *base, *ptr, *top, *del, *node, *name, *ext, ch; char **hostaddrlist; char def_string[MAX_FBUFF + 1]; boolean_t hasnode, hasdir, hasname, hasext, wilddir, wildname; enum parse_state state; struct sockaddr_storage query_sas; struct sockaddr localhost_sa, *localhost_sa_ptr; mval def_trans; int errcode; pblk->fnb = 0; ai_ptr = localhost_ai_ptr = temp_ai_ptr = NULL; assert(((unsigned int)pblk->buff_size + 1) <= (MAX_FBUFF + 1)); /* All callers of parse_blk set buff_size to 1 less than the allocated buffer. This is because buff_size is a char * type (for historical reasons) and so cannot go more than 255 whereas we support a max of 255 characters. So we * allocate buffers that contain one more byte (for the terminating '\0') but dont set that in buff_size. Use * that extra byte for the trans_log_name call. */ status = TRANS_LOG_NAME(file, &trans, pblk->buffer, pblk->buff_size + 1, dont_sendmsg_on_log2long); if (SS_LOG2LONG == status) return ERR_PARBUFSM; assert(trans.addr == pblk->buffer); memset(&def, 0, SIZEOF(def)); /* Initial the defaults to zero */ if (pblk->def1_size > 0) { /* Parse default filespec if supplied */ def.fop = F_SYNTAXO; def.buffer = def_string; def.buff_size = MAX_FBUFF; def.def1_size = pblk->def2_size; def.def1_buf = pblk->def2_buf; tmp.len = pblk->def1_size; tmp.addr = pblk->def1_buf; if ((status = parse_file(&tmp, &def)) != ERR_PARNORMAL) return status; assert(!def.b_node); if (def.b_dir) def.fnb |= F_HAS_DIR; if (def.b_name) def.fnb |= F_HAS_NAME; if (def.b_ext) def.fnb |= F_HAS_EXT; } wildname = wilddir = hasnode = hasdir = hasname = hasext = FALSE; node = base = ptr = trans.addr; top = ptr + trans.len; if ((0 == trans.len) || ('/' != *ptr)) { /* No file given, no full path given, or a nodename was specified */ setzdir(NULL, &def_trans); /* Default current directory if none given */ assert((0 == dollar_zdir.str.len) /* dollar_zdir not initialized yet, possible thru main() -> gtm_chk_dist() */ || ((def_trans.str.len == dollar_zdir.str.len) /* Check if cwd and cached value are the same */ && (0 == memcmp(def_trans.str.addr, dollar_zdir.str.addr, def_trans.str.len)))); if (pblk->fop & F_PARNODE) { /* What we have could be a nodename */ assert(pblk->fop & F_SYNTAXO); while (node < top) { ch = *node++; if (':' == ch) /* We have nodeness */ break; if ('/' == ch) { /* Not a node - bypass node checking */ node = top; break; } } if (node < top) { hasnode = TRUE; ptr = base = node; /* Update pointers past node name */ /* See if the desired (query) node is the local node */ node_name_len = (int)(node - trans.addr); /* Scanned node including ':' */ query_node_len = node_name_len - 1; /* Pure name length, no ':' on end */ assert(MAX_HOST_NAME_LEN >= query_node_len); assert(0 < query_node_len); assert(':' == *(trans.addr + query_node_len)); memcpy(query_node_name, trans.addr, query_node_len); query_node_name[query_node_len] = 0; localhost_sa_ptr = NULL; /* Null value needed if not find query node (remote default) */ CLIENT_HINTS(hints); if (0 != (errcode = getaddrinfo(query_node_name, NULL, &hints, &ai_ptr))) /* Assignment! */ ai_ptr = NULL; /* Skip additional lookups */ else memcpy((sockaddr_ptr)&query_sas, ai_ptr->ai_addr, ai_ptr->ai_addrlen); CLIENT_HINTS(hints); if (0 == (errcode = getaddrinfo(LOCALHOSTNAME, NULL, &hints, &localhost_ai_ptr)) && (0 == memcmp(localhost_ai_ptr->ai_addr, (sockaddr_ptr)&query_sas, localhost_ai_ptr->ai_addrlen))) { localhost_sa_ptr = localhost_ai_ptr->ai_addr; } FREEADDRINFO(localhost_ai_ptr); if (ai_ptr && !localhost_sa_ptr) { /* Have not yet established this is not a local node -- check further */ GETHOSTNAME(local_node_name, MAX_HOST_NAME_LEN, status); if (-1 == status) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("gethostname"), CALLFROM, errno); CLIENT_HINTS(hints); if (0 != (errcode = getaddrinfo(local_node_name, NULL, &hints, &localhost_ai_ptr))) localhost_ai_ptr = NULL; /* Empty address list */ for (temp_ai_ptr = localhost_ai_ptr; temp_ai_ptr!= NULL; temp_ai_ptr = temp_ai_ptr->ai_next) { if (0 == memcmp((sockaddr_ptr)&query_sas, temp_ai_ptr->ai_addr, temp_ai_ptr->ai_addrlen)) { localhost_sa_ptr = temp_ai_ptr->ai_addr; break; /* Tiz truly a local node */ } } FREEADDRINFO(localhost_ai_ptr); } if (ai_ptr && !localhost_sa_ptr) { CLIENT_HINTS(hints); if (0 != (errcode = getaddrinfo(LOCALHOSTNAME6, NULL, &hints, &localhost_ai_ptr))) localhost_ai_ptr = NULL; /* Empty address list */ for (temp_ai_ptr = localhost_ai_ptr; temp_ai_ptr!= NULL; temp_ai_ptr = temp_ai_ptr->ai_next) { if (0 == memcmp((sockaddr_ptr)&query_sas, temp_ai_ptr->ai_addr, temp_ai_ptr->ai_addrlen)) { localhost_sa_ptr = temp_ai_ptr->ai_addr; break; /* Tiz truly a local node */ } } FREEADDRINFO(localhost_ai_ptr); } if (!localhost_sa_ptr) /* Not local (or an unknown) host given */ { /* Remote node specified -- don't apply any defaults */ FREEADDRINFO(ai_ptr); pblk->l_node = trans.addr; pblk->b_node = node_name_len; pblk->l_dir = base; pblk->b_dir = top - base; pblk->l_name = pblk->l_ext = base + pblk->b_dir; pblk->b_esl = pblk->b_node + pblk->b_dir; pblk->b_name = pblk->b_ext = 0; pblk->fnb |= (hasnode << V_HAS_NODE); return ERR_PARNORMAL; } FREEADDRINFO(ai_ptr); /* Remove local node name from filename buffer */ assert(0 < trans.len - node_name_len); memmove(trans.addr, node, trans.len - node_name_len); ptr = base = node -= node_name_len; top -= node_name_len; trans.len -= node_name_len; if ('/' == *base) /* No default directory if full path given */ def_trans.str.len = 0; } else { /* Supplied text was not a node -- reset pointer back to beginning for rescan */ node = trans.addr; } } /* If parse buffer is not large enough, return error */ if (def_trans.str.len + trans.len > pblk->buff_size) return ERR_PARBUFSM; /* Construct full filename to parse prefixing given filename with default path prefix */ if (0 < def_trans.str.len) { memmove(ptr + def_trans.str.len, ptr, trans.len); memcpy(ptr, def_trans.str.addr, def_trans.str.len); assert('/' == ptr[def_trans.str.len - 1]); ptr += def_trans.str.len; top += def_trans.str.len; } } name = ptr; state = NOSTATE; for (; ptr < top;) { ch = *ptr; if ('.' == ch) { /* Could be /./ or /../ or name.name */ ptr++; state = (DOT1 == state) ? ((DOT2 == state) ? NAME : DOT2) : DOT1; } else if (ch == '/') { /* We must still be doing the path */ ptr++; hasdir = TRUE; hasname = FALSE; hasext = FALSE; wilddir |= wildname; wildname = FALSE; if ((DOT1 != state) && (DOT2 != state) && (SLASH != state)) { /* No dots seen recently so scan as if this is start of filename */ state = SLASH; name = ptr; continue; } if (DOT1 == state) { /* Just remove "./" chars from path */ del = ptr - 2; } else if (DOT2 == state) { /* Have xx/../ construct. Remove /../ and previous level directory from path */ del = ptr - 4; /* /../ characters being removed */ assert ('/' == *del); if (del > base) { del--; while ('/' != *del) del--; } assert((del >= base) && ('/' == *del)); del++; } else if (SLASH == state) { /* Remove duplicate slash from path */ del = ptr - 1; while ((ptr < top) && ('/' == *ptr)) ptr++; } memmove(del, ptr, top - ptr); diff = (int)(ptr - del); ptr -= diff; top -= diff; state = SLASH; name = ptr; } else { /* Hopeful of filename */ hasname = TRUE; while (ptr < top) /* Do small scan looking for filename end */ { ch = *ptr; if ('/' == ch) break; /* Ooops, still doing path */ if ('.' == ch) {/* Filename has an extension */ hasext = TRUE; ext = ptr; } else if (('?' == ch) || ('*' == ch)) wildname = TRUE; ptr++; } state = NAME; } } /* Handle scan end with non-normal state */ if ((SLASH == state) || (DOT1 == state) || (DOT2 == state)) { assert(!hasname && !hasext); hasdir = TRUE; if (state == DOT1) { /* Ignore ./ */ top--; ptr--; } if (DOT2 == state) { /* Ignore ../ plus last directory level specified */ del = ptr - 3; /* on the end */ assert ('/' == *del); if (del > base) { del--; while ('/' != *del) del--; } assert((del >= base) && ('/' == *del)); del++; ptr = top = del; name = ptr; } } if (!hasname) { assert(!hasext); name = ptr; if (def.fnb & F_HAS_NAME) { /* Use default filename if we didn't find one */ diff = (int)(name - node); if (def.b_name + diff > pblk->buff_size) return ERR_PARBUFSM; memcpy(name, def.l_name, def.b_name); ptr += def.b_name; } ext = ptr; } if (!hasext) { ext = ptr; if (def.fnb & F_HAS_EXT) { /* Use default file extension if we didn't find one */ diff = (int)((ext - node)); if (def.b_ext + diff > pblk->buff_size) return ERR_PARBUFSM; memcpy(ext, def.l_ext, def.b_ext); ptr += def.b_ext; } } pblk->b_name = ext - name; pblk->b_ext = ptr - ext; if (!hasdir && (def.fnb & F_HAS_DIR)) { diff = (int)(name - base); diff = def.b_dir - diff; if (def.b_dir + pblk->b_name + pblk->b_ext > pblk->buff_size) return ERR_PARBUFSM; if (diff > 0) memmove(name + diff, name, pblk->b_name + pblk->b_ext); else if (diff < 0) memcpy(name + diff, name, pblk->b_name + pblk->b_ext); memcpy(base, def.l_dir, def.b_dir); ptr += diff; name += diff; } pblk->b_dir = name - base; pblk->b_esl = ptr - base; pblk->l_dir = base; pblk->l_name = base + pblk->b_dir; pblk->l_ext = pblk->l_name + pblk->b_name; pblk->fnb |= (hasdir << V_HAS_DIR); pblk->fnb |= (hasname << V_HAS_NAME); pblk->fnb |= (hasext << V_HAS_EXT); pblk->fnb |= (wildname << V_WILD_NAME); pblk->fnb |= (wilddir << V_WILD_DIR); if (!(pblk->fop & F_SYNTAXO) && !wilddir) { assert('/' == pblk->l_dir[pblk->b_dir - 1]); if (pblk->b_dir > 1) { pblk->l_dir[pblk->b_dir - 1] = 0; STAT_FILE(pblk->l_dir, &statbuf, status); pblk->l_dir[pblk->b_dir - 1] = '/'; if ((-1 == status) || !(statbuf.st_mode & S_IFDIR)) return ERR_FILENOTFND; } } return ERR_PARNORMAL; }