int main(){ int cCase = 0; char name[5]; while(scanf("%s", name), name[0]!='0'){ printf("Case %d:", ++cCase); memset(nId, 0, sizeof(nId)); nId[name2id(name)]++; for(int i = 1; i<13; i++){ scanf("%s", name); nId[name2id(name)]++; } bool ready = 0; for(int i = 0; i<34; i++) if((nId[i] || (i-1 && nId[i-1]) || (i+1<34 && nId[i+1]))&&nId[i]<4){ nId[i]++; if(hu()){ printf(" %s", id2name[i]); ready = 1; } nId[i]--; } if(!ready) printf(" Not ready"); printf("\n"); } return 0; }
static int pc1auth(int n, Rpccall *cmd, Rpccall *reply) { uchar *argptr = cmd->args; uchar *dataptr = reply->results; String id, pw; Unixidmap *m; int uid; chat("host=%I, port=%ld: pcauth...", cmd->host, cmd->port); if(n <= 8) return garbage(reply, "count too small"); argptr += string2S(argptr, &id); argptr += string2S(argptr, &pw); if(argptr != &((uchar*)cmd->args)[n]) return garbage(reply, "bad count"); scramble(&id); scramble(&pw); m = pair2idmap("pcnfsd", cmd->host); uid = -1; if(m) uid = name2id(&m->u.ids, id.s); if(uid < 0) uid = 1; chat("\"%.*s\",\"%.*s\" uid=%d\n", utfnlen(id.s, id.n), id.s, utfnlen(pw.s, pw.n), pw.s, uid); PLONG(0); /* status */ PLONG(uid); /* uid */ PLONG(uid); /* gid */ return dataptr - (uchar*)reply->results; }
sparc_cc Sparc_map_FCC(const char *name) { unsigned int i; i = name2id(alias_fcc_maps, ARR_SIZE(alias_fcc_maps), name); return (i != -1)? i : SPARC_CC_INVALID; }
// map instruction name to instruction ID (public) sparc_reg Sparc_map_insn(const char *name) { unsigned int i; // NOTE: skip first NULL name in insn_name_maps i = name2id(&insn_name_maps[1], ARR_SIZE(insn_name_maps) - 1, name); return (i != -1)? i : SPARC_REG_INVALID; }
// map instruction name to public instruction ID mips_reg Mips_map_insn(const char *name) { // handle special alias first unsigned int i; // NOTE: skip first NULL name in insn_name_maps i = name2id(&insn_name_maps[1], ARR_SIZE(insn_name_maps) - 1, name); return (i != -1)? i : MIPS_REG_INVALID; }
/* * this function converts a string of resources into a buffer which then * can be used for acctctl() system call */ void str2buf(ac_res_t *buf, char *str, int state, int type) { int i, j, id, ok; char *p, *g, *copy; if (strcmp(str, AC_STR_NONE) == 0) return; /* * Take a lap through str, processing resources, modifying buf copy * as appropriate and making sure that all resource names are valid. */ if ((copy = malloc(strlen(str) + 1)) == NULL) die(gettext("not enough memory\n")); (void) memcpy(copy, str, strlen(str) + 1); p = strtok(copy, ", "); while (p != NULL) { /* * check if str contains any resource groups */ for (ok = 0, i = 0; (g = ac_groups[i].ag_name) != NULL; i++) { if (strcmp(p, g) == 0 && ac_groups[i].ag_type == type) { for (j = 0; (id = ac_groups[i].ag_mem[j]) != AC_NONE; j++) resset(buf, id, state); ok = 1; break; } } if (ok == 0) { id = name2id(p, type); if (id > 0) resset(buf, id, state); else if (id == 0) die(gettext("unknown %s resource: %s\n"), type == AC_PROC ? "process" : "task", p); } p = strtok(NULL, ", "); } free(copy); }
static int pcauth(int n, Rpccall *cmd, Rpccall *reply) { uchar *argptr = cmd->args; uchar *dataptr = reply->results; String sys, id, pw, cm; Unixidmap *m; int uid; chat("host=%I, port=%ld: pcauth...", cmd->host, cmd->port); if(n <= 16) return garbage(reply, "count too small"); argptr += string2S(argptr, &sys); argptr += string2S(argptr, &id); argptr += string2S(argptr, &pw); argptr += string2S(argptr, &cm); if(argptr != &((uchar *)cmd->args)[n]) return garbage(reply, "bad count"); scramble(&id); scramble(&pw); m = pair2idmap("pcnfsd", cmd->host); uid = -1; if(m) uid = name2id(&m->u.ids, id.s); if(uid < 0) uid = 1; chat("\"%.*s\",\"%.*s\",\"%.*s\",\"%.*s\"\n", utfnlen(sys.s, sys.n), sys.s, utfnlen(id.s, id.n), id.s, utfnlen(pw.s, pw.n), pw.s, utfnlen(cm.s, cm.n), cm.s); PLONG(0); /* status - OK */ PLONG(uid); PLONG(uid); /* gid */ PLONG(0); /* ngids */ PLONG(sizeof(pc_home)-1); PPTR(pc_home, sizeof(pc_home)-1); PLONG(0); /* umask */ PLONG(sizeof(no_comment)-1); PPTR(no_comment, sizeof(no_comment)-1); return dataptr - (uchar *)reply->results; }
static void user_inodes_grace_time_test(long isoftlimit, long bsoftlimit, long grace_seconds, long user_postfix) { int ret, fd, o_uid; long i; struct if_dqblk s_dq, d_dq; struct if_dqinfo s_dqi; char username[USERNAME_SZ]; snprintf(username, USERNAME_SZ, "quota-user-rank%d-%ld", rank, user_postfix); add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL); getquota(QUOTAUSER, device, name2id(USER, username), &s_dq); s_dq.dqb_isoftlimit = isoftlimit; s_dq.dqb_ihardlimit = isoftlimit * 2; s_dq.dqb_bsoftlimit = bsoftlimit; s_dq.dqb_bhardlimit = bsoftlimit * 2; s_dq.dqb_curinodes = 0; s_dq.dqb_curspace = 0; setquota(QUOTAUSER, device, name2id(USER, username), s_dq); getquotainfo(QUOTAUSER, device, name2id(USER, username), &s_dqi); s_dqi.dqi_bgrace = 60000; s_dqi.dqi_igrace = grace_seconds; setquotainfo(QUOTAUSER, device, name2id(USER, username), s_dqi); o_uid = getuid(); seteuid(name2id(USER, username)); for (i = 0; i <= isoftlimit ; i++) { snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%ld", workplace, hostname, username, i); fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE); if (fd < 0) { ret = errno; abort_printf("Open file failed:%d:%s\n", ret, strerror(ret)); } close(fd); getquota(QUOTAUSER, device, name2id(USER, username), &d_dq); if (d_dq.dqb_curinodes != i + 1) abort_printf("Incorrect quota stats found,expected " "inode_num = %d,queried inode_num = %d.\n", i + 1, d_dq.dqb_curinodes); } /*Grace time take effect from now*/ sleep(grace_seconds); /*grace time expires,so should hit failure here*/ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%ld", workplace, hostname, username, isoftlimit + 1); if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) > 0) { close(fd); abort_printf("Not allowd to exceed the grace time limit of inodes.\n"); } /*cleanup*/ seteuid(o_uid); for (i = 0; i <= isoftlimit; i++) { snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%ld", workplace, hostname, username, i); ret = unlink(filename); if (ret < 0) { ret =errno; abort_printf("Failed to unlink file(%s):%d:%s\n", filename, ret, strerror(ret)); } } add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL); }
void main(int argc, char **argv) { int id, arc; char *arv[4]; char *l, *name; chatty = 1; ARGBEGIN{ case '9': case 'u': style = ARGC(); break; case 'D': ++debug; break; }ARGEND if(argc <= 0){ ids = readunixids("/fd/0", style); if(ids) idprint(1, ids); exits(ids ? 0 : "readunixids"); } mapinit(argv[0], 0); in = Bopen("/fd/0", OREAD); while(l = Brdline(in, '\n')){ /* assign = */ l[Blinelen(in)-1] = 0; arc = strparse(l, nelem(arv), arv); if(arc <= 0) continue; switch(arv[0][0]){ case 'r': if(arc < 2) continue; mapinit(arv[1], arv[2]); break; case 'i': if(arc < 2) continue; id = strtol(arv[1], 0, 10); name = id2name(pids, id); print("%d -> %s\n", id, name); break; case 'n': if(arc < 2) continue; name = arv[1]; id = name2id(pids, name); print("%s -> %d\n", name, id); break; case 'p': print("server=%s, client=%s\n", mp->server, mp->client); break; case 'P': idprint(1, *pids); break; case 'u': pids = &mp->u.ids; print("users...\n"); break; case 'g': pids = &mp->g.ids; print("groups...\n"); break; } } exits(0); }
int main(int argc, char ** argv) { long templ; pthread_t tid; pid_t pid; char *config=NULL; iface_t *engine; struct if_engine *ifg; iface_t *ifptr,*ifptr2,*rptr; iface_t **tiptr; unsigned int i=1; int opt,err=0; void *ret; struct kopts *options=NULL; sigset_t set; struct iolists lists = { /* initialize io_mutex separately below */ .init_mutex = PTHREAD_MUTEX_INITIALIZER, .init_cond = PTHREAD_COND_INITIALIZER, .dead_cond = PTHREAD_COND_INITIALIZER, .initialized = NULL, .outputs = NULL, .inputs = NULL, .dead = NULL }; struct rlimit lim; int gotinputs=0; int rcvdsig; struct sigaction sa; pthread_mutex_init(&lists.io_mutex,NULL); /* command line argument processing */ while ((opt=getopt(argc,argv,"d:f:o:V")) != -1) { switch (opt) { case 'd': if ((((templ=strtol(optarg,NULL,0)) == 0) && (errno == EINVAL || errno == ERANGE )) || (templ < 0) || (templ > 9)) { logerr(errno,"Bad debug level %s: Must be 1-9",optarg); err++; } else debuglevel=templ; break; case 'o': if (cmdlineopt(&options,optarg) < 0) err++; break; case 'f': config=optarg; break; case 'V': printf("%s\n",VERSION); if (argc == 2) exit(0); else err++; break; default: err++; } } if (err) { fprintf(stderr, "Usage: %s [-V] | [ -f <config file>] [-o <option=value>]... [<interface specification> ...]\n",argv[0]); exit(1); } /* If a config file is specified by a commad line argument, read it. If * not, look for a default config file unless told not to using "-f-" on the * command line */ if ((config && (strcmp(config,"-"))) || (!config && (config = get_def_config()))) { DEBUG(1,"Using config file %s",config); if ((engine=parse_file(config)) == NULL) { fprintf(stderr,"Error parsing config file: %s\n",errno? strerror(errno):"Syntax Error"); exit(1); } } else { /* global options for engine configuration are also returned in config * file parsing. If we didn't do that, get default options here */ DEBUG(1,"Not using config file"); engine = get_default_global(); } proc_engine_options(engine,options); engine->lists = &lists; lists.engine=engine; for (tiptr=&engine->next;optind < argc;optind++) { if (!(ifptr=parse_arg(argv[optind]))) { fprintf(stderr,"Failed to parse interface specifier %s\n", argv[optind]); exit(1); } ifptr->next=(*tiptr); (*tiptr)=ifptr; tiptr=&ifptr->next; } /* We choose to go into the background here before interface initialzation * rather than later. Disadvantage: Errors don't get fed back on stderr. * Advantage: We can close all the file descriptors now rather than pulling * then from under erroneously specified stdin/stdout etc. */ ifg=(struct if_engine *)engine->info; if (ifg->flags & K_BACKGROUND) { if ((pid = fork()) < 0) { perror("fork failed"); exit(1); } else if (pid) exit(0); /* Continue here as child */ /* Really should close all file descriptors. Harder to do in OS * independent way. Just close the ones we know about for this cut * Check first if connected to a tty to allow redirection / piping in * background mode */ if (isatty(fileno(stdin))) { fclose(stdin); ifg->flags |= K_NOSTDIN; } if (isatty(fileno(stdout))) { fclose(stdout); ifg->flags |= K_NOSTDOUT; } if (isatty(fileno(stderr))) { fclose(stderr); ifg->flags |= K_NOSTDERR; } setsid(); (void) chdir("/"); umask(0); } /* log to stderr or syslog, as appropriate */ initlog((ifg->flags & K_NOSTDERR)?ifg->logto:-1); /* Lower max open files if necessary. We do this to ensure that ids for * all connections can be represented in IDMINORBITS. Actually we only * need to do that per server, so this is a bit of a hack and should be * corrected */ if (getrlimit(RLIMIT_NOFILE,&lim) < 0) logterm(errno,"Couldn't get resource limits"); if (lim.rlim_cur > 1<<IDMINORBITS) { logwarn("Lowering NOFILE from %u to %u",lim.rlim_cur,1<<IDMINORBITS); lim.rlim_cur=1<<IDMINORBITS; if(setrlimit(RLIMIT_NOFILE,&lim) < 0) logterm(errno,"Could not set file descriptor limit"); } /* our list of "real" interfaces starts after the first which is the * dummy "interface" specifying the multiplexing engine * walk the list, initialising the interfaces. Sometimes "BOTH" interfaces * are initialised to one IN and one OUT which then need to be linked back * into the list */ for (ifptr=engine->next,tiptr=&lists.initialized,i=0;ifptr;ifptr=ifptr2) { ifptr2 = ifptr->next; if (i == MAXINTERFACES) logterm(0,"Too many interfaces"); ifptr->id=++i<<IDMINORBITS; if (ifptr->name) { if (insertname(ifptr->name,ifptr->id) < 0) logterm(errno,"Failed to associate interface name and id"); } ifptr->lists = &lists; if ((rptr=(*iftypes[ifptr->type].init_func)(ifptr)) == NULL) { logerr(0,"Failed to initialize Interface %s",(ifptr->name)? ifptr->name:"(unnamed)"); if (!flag_test(ifptr,F_OPTIONAL)) { timetodie++; break; } /* Free all resources associated with interface * This is a bigger task than it looks. Before the "optional" * flag this was not an issue as we'd just be exiting after this * Now we need to clean up properly but not yet implemented. This * is a little memory leak with each failed init attempt */ free(ifptr); continue; } for (;ifptr;ifptr = ifptr->next) { /* This loop should be done once for IN or OUT interfaces twice for * interfaces where the initialisation routine has expanded them to an * IN/OUT pair. */ if (ifptr->direction == IN) ifptr->q=engine->q; if (ifptr->checksum <0) ifptr->checksum = engine->checksum; if (ifptr->strict <0) ifptr->strict = engine->strict; (*tiptr)=ifptr; tiptr=&ifptr->next; if (ifptr->next==ifptr2) ifptr->next=NULL; } } /* One more spin through the list now we've initialised the name to id * mapping so we can update references to "name" with an id */ for (ifptr=engine->next;ifptr;ifptr=ifptr->next) { if (ifptr->ofilter) if (name2id(ifptr->ofilter)) logterm(errno,"Name to interface translation failed"); } /* Create the key for thread local storage: in this case for a pointer to * the interface each thread is handling */ if (pthread_key_create(&ifkey,iface_destroy)) { logerr(errno,"Error creating key"); timetodie++; } if (timetodie) { for (ifptr=lists.initialized;ifptr;ifptr=ifptr2) { ifptr2=ifptr->next; iface_destroy(ifptr); } exit(1); } if (name2id(engine->ofilter)) logterm(errno,"Failed to translate interface names to IDs"); if (engine->options) free_options(engine->options); pthread_setspecific(ifkey,(void *)&lists); reaper=pthread_self(); sigemptyset(&set); sigemptyset(&sa.sa_mask); sa.sa_handler=terminate; sa.sa_flags=0; sigaction(SIGUSR1,&sa,NULL); sigaddset(&set,SIGUSR1); sigaddset(&set,SIGUSR2); sigaddset(&set,SIGALRM); sigaddset(&set,SIGTERM); sigaddset(&set,SIGINT); pthread_sigmask(SIG_BLOCK, &set, NULL); sigdelset(&set,SIGUSR1); signal(SIGPIPE,SIG_IGN); pthread_create(&tid,NULL,run_engine,(void *) engine); pthread_mutex_lock(&lists.io_mutex); for (ifptr=lists.initialized;ifptr;ifptr=ifptr->next) { /* Check we've got at least one input */ if ((ifptr->direction == IN ) || (ifptr->direction == BOTH)) gotinputs=1; /* Create a thread to run each interface */ pthread_create(&tid,NULL,(void *)start_interface,(void *) ifptr); } while (lists.initialized) pthread_cond_wait(&lists.init_cond,&lists.io_mutex); /* Have to wait until here to do something about no inputs to * avoid deadlock on io_mutex */ if (!gotinputs) { logerr(0,"No Inputs!"); pthread_mutex_lock(&engine->q->q_mutex); engine->q->active=0; pthread_cond_broadcast(&engine->q->freshmeat); pthread_mutex_unlock(&engine->q->q_mutex); timetodie++; } /* While there are remaining outputs, wait until something is added to the * dead list, reap everything on the dead list and check for outputs again * until all the outputs have been reaped * Note that when there are no more inputs, we set the * engine's queue inactive causing it to set all the outputs' queues * inactive and shutting them down. Thus the last input exiting also shuts * everything down */ while (lists.outputs || lists.inputs || lists.dead) { if (lists.dead == NULL && (timetodie <= 0)) { pthread_mutex_unlock(&lists.io_mutex); /* Here we're waiting for SIGTERM/SIGINT (user shutdown requests), * SIGUSR2 (notifications of termination from interface threads) * and (later) SIGALRM to notify of the grace period expiry */ (void) sigwait(&set,&rcvdsig); pthread_mutex_lock(&lists.io_mutex); } if ((timetodie > 0) || ( lists.outputs == NULL && (timetodie == 0)) || rcvdsig == SIGTERM || rcvdsig == SIGINT) { timetodie=-1; /* Once we've caught a user shutdown address we don't need to be * told twice */ signal(SIGTERM,SIG_IGN); signal(SIGINT,SIG_IGN); sigdelset(&set,SIGTERM); sigdelset(&set,SIGINT); for (ifptr=lists.inputs;ifptr;ifptr=ifptr->next) { pthread_kill(ifptr->tid,SIGUSR1); } for (ifptr=lists.outputs;ifptr;ifptr=ifptr->next) { if (ifptr->q == NULL) pthread_kill(ifptr->tid,SIGUSR1); } /* Set up the graceperiod alarm */ if (graceperiod) alarm(graceperiod); } if (rcvdsig == SIGALRM || graceperiod == 0) { sigdelset(&set,SIGALRM); /* Make sure we don't come back here with 0 graceperiod */ if (graceperiod == 0) graceperiod=1; for (ifptr=lists.outputs;ifptr;ifptr=ifptr->next) { if (ifptr->q) pthread_kill(ifptr->tid,SIGUSR1); } } for (ifptr=lists.dead;ifptr;ifptr=lists.dead) { lists.dead=ifptr->next; pthread_join(ifptr->tid,&ret); free(ifptr); } } /* For neatness... */ pthread_mutex_unlock(&lists.io_mutex); exit(0); }
/** * @brief Convert a name to a uid * * @param[in] name The name of the user * @param[out] uid The resulting UID * @param[in] anon The anonymous UID for this export * * @return true if successful, false otherwise * */ bool name2uid(const struct gsh_buffdesc *name, uid_t *uid, const uid_t anon) { return name2id(name, uid, false, anon); }
static void group_space_limit_test(long isoftlimit, long bsoftlimit, long user_num, int grp_postfix) { int ret = 0, fd; long i; int o_uid, o_gid; struct if_dqblk s_dq; char username[USERNAME_SZ], groupname[GROUPNAME_SZ]; char *write_buf; int writen_sz, user_index; long file_sz = 0, count = 0; write_buf = (char *)malloc(clustersize); memset(write_buf, 0, clustersize); snprintf(groupname, GROUPNAME_SZ, "quotagroup-rank%d-%d", rank, grp_postfix); add_rm_user_group(GROUPADD_BIN, ADD, GROUP, groupname, NULL); getquota(QUOTAGROUP, device, name2id(GROUP, groupname), &s_dq); s_dq.dqb_isoftlimit = isoftlimit; s_dq.dqb_ihardlimit = isoftlimit * 2; s_dq.dqb_bsoftlimit = bsoftlimit; s_dq.dqb_bhardlimit = bsoftlimit * 2; s_dq.dqb_curinodes = 0; s_dq.dqb_curspace = 0; setquota(QUOTAGROUP, device, name2id(GROUP, groupname), s_dq); o_gid = getgid(); setegid(name2id(GROUP, groupname)); for (i = 0; i < user_num; i++) { snprintf(username, USERNAME_SZ, "%s-quotauser-%ld", groupname, i); add_rm_user_group(USERADD_BIN, ADD, USER_IN_GROUP, username, groupname); getquota(QUOTAUSER, device, name2id(USER, username), &s_dq); s_dq.dqb_isoftlimit = isoftlimit; s_dq.dqb_ihardlimit = isoftlimit * 2; s_dq.dqb_bsoftlimit = bsoftlimit; s_dq.dqb_bhardlimit = bsoftlimit * 2; s_dq.dqb_curinodes = 0; s_dq.dqb_curspace = 0; setquota(QUOTAUSER, device, name2id(USER, username), s_dq); o_uid = getuid(); seteuid(name2id(USER, username)); snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-group-spacelimit", workplace, hostname, username); fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE); if (fd < 0) abort_printf("Create file failed:%d:%s.\n", ret, strerror(ret)); close(fd); seteuid(o_uid); } while (file_sz + clustersize <= bsoftlimit * 2 * 1024) { user_index = count % user_num; snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname, user_index); snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-group-spacelimit", workplace, hostname, username); o_uid = getuid(); seteuid(name2id(USER, username)); fd = open(filename, O_RDWR | O_APPEND, FILE_MODE); writen_sz = write(fd, write_buf, clustersize); if (writen_sz < 0) { ret = errno; abort_printf("write failed:%d:%s.\n", ret, strerror(ret)); } close(fd); seteuid(o_uid); file_sz += writen_sz; count++; } user_index = count % user_num; snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname, user_index); snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-group-spacelimit", workplace, hostname, username); o_uid = getuid(); seteuid(name2id(USER, username)); fd = open(filename, O_RDWR | O_APPEND, FILE_MODE); if ((writen_sz = write(fd, write_buf, clustersize)) > 0) abort_printf("Not allowed to exceed space hard limit of group."); close(fd); seteuid(o_uid); setegid(o_gid); for (i = 0; i < user_num; i++) { snprintf(username, USERNAME_SZ, "%s-quotauser-%ld", groupname, i); snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-group-spacelimit", workplace, hostname, username); ret = unlink(filename); if (ret < 0) { ret = errno; abort_printf("Failed to unlink file %s:%d:%s.\n", filename, ret, strerror(ret)); } add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL); } sync(); add_rm_user_group(GROUPDEL_BIN, REMOVE, GROUP, groupname, NULL); if (write_buf) free(write_buf); }
static void group_inodes_limit_test(long isoftlimit, long bsoftlimit, long user_num, int grp_postfix) { int ret, fd; long i; int o_uid, o_gid; int user_index; struct if_dqblk s_dq, d_dq; char username[USERNAME_SZ], groupname[GROUPNAME_SZ]; snprintf(groupname, GROUPNAME_SZ, "quotagroup-rank%d-%d", rank, grp_postfix); add_rm_user_group(GROUPADD_BIN, ADD, GROUP, groupname, NULL); getquota(QUOTAGROUP, device, name2id(GROUP, groupname), &s_dq); s_dq.dqb_isoftlimit = isoftlimit; s_dq.dqb_ihardlimit = isoftlimit * 2; s_dq.dqb_bsoftlimit = bsoftlimit; s_dq.dqb_bhardlimit = bsoftlimit * 2; s_dq.dqb_curinodes = 0; s_dq.dqb_curspace = 0; setquota(QUOTAGROUP, device, name2id(GROUP, groupname), s_dq); for (i = 0; i < user_num; i++) { snprintf(username, USERNAME_SZ, "%s-quotauser-%ld", groupname, i); add_rm_user_group(USERADD_BIN, ADD, USER_IN_GROUP, username, groupname); getquota(QUOTAUSER, device, name2id(USER, username), &s_dq); s_dq.dqb_isoftlimit = isoftlimit; s_dq.dqb_ihardlimit = isoftlimit * 2; s_dq.dqb_bsoftlimit = bsoftlimit; s_dq.dqb_bhardlimit = bsoftlimit * 2; s_dq.dqb_curinodes = 0; s_dq.dqb_curspace = 0; setquota(QUOTAUSER, device, name2id(USER, username), s_dq); } o_gid = getgid(); setegid(name2id(GROUP, groupname)); for (i = 0; i < isoftlimit * 2; i++) { user_index = i % user_num; snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname, user_index); snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%ld", workplace, hostname, username, i); o_uid = getuid(); seteuid(name2id(USER, username)); fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE); if (fd < 0) { ret = errno; abort_printf("Open %d file failed:%d:%s\n", i, ret, strerror(ret)); } close(fd); seteuid(o_uid); getquota(QUOTAGROUP, device, name2id(GROUP, groupname), &d_dq); if (d_dq.dqb_curinodes != i + 1) abort_printf("Incorrect quota stats found,expected " "inode_num = %d,queried inode_num = %d.\n", i + 1, d_dq.dqb_curinodes); } /*We definitely should hit falure here*/ user_index = (isoftlimit * 2) % user_num; snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname, user_index); snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%ld", workplace, hostname, username, isoftlimit * 2); o_uid = getuid(); seteuid(name2id(USER, username)); if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) > 0) { close(fd); abort_printf("Not allowd to exceed the hard limit of inodes.\n"); } seteuid(o_uid); setegid(o_gid); /*cleanup*/ for (i = 0; i < isoftlimit * 2; i++) { user_index = i % user_num; snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname, user_index); snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%ld", workplace, hostname, username, i); ret = unlink(filename); if (ret < 0) { ret =errno; abort_printf("Failed to unlink file(%s):%d:%s\n", filename, ret, strerror(ret)); } } for (i = 0; i < user_num; i++) { snprintf(username, USERNAME_SZ, "%s-quotauser-%ld", groupname, i); add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL); } add_rm_user_group(GROUPDEL_BIN, REMOVE, GROUP, groupname, NULL); }
static void user_space_limit_test(long isoftlimit, long bsoftlimit, int user_postfix) { int ret, fd; int o_uid; struct if_dqblk s_dq; char *write_buf; int writen_sz = 0; long file_sz = 0; char username[USERNAME_SZ]; write_buf = (char *)malloc(clustersize); memset(write_buf, 0, clustersize); snprintf(username, USERNAME_SZ, "quotauser-rank%d-%d", rank, user_postfix); add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL); getquota(QUOTAUSER, device, name2id(USER, username), &s_dq); s_dq.dqb_isoftlimit = isoftlimit; s_dq.dqb_ihardlimit = isoftlimit * 2; s_dq.dqb_bsoftlimit = bsoftlimit; s_dq.dqb_bhardlimit = bsoftlimit * 2; s_dq.dqb_curinodes = 0; s_dq.dqb_curspace = 0; setquota(QUOTAUSER, device, name2id(USER, username), s_dq); o_uid = getuid(); ret = seteuid(name2id(USER, username)); if (ret < 0) { ret = errno; abort_printf("Set euid failed:%d:%s.\n", ret, strerror(ret)); } snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-user-spacelimit", workplace, hostname, username); fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, FILE_MODE); while (file_sz + clustersize <= bsoftlimit * 2 * 1024) { writen_sz = write(fd, write_buf, clustersize); if (writen_sz < 0) { ret = errno; abort_printf("write failed:%d:%s.\n", ret, strerror(ret)); } file_sz += writen_sz; } if ((ret = write(fd, write_buf, clustersize)) > 0) abort_printf("No allowed to exceed the hard limit of space"); if (fd) close(fd); ret = unlink(filename); if (ret < 0) { ret =errno; abort_printf("Failed to unlink file(%s):%d:%s\n", filename, ret, strerror(ret)); } sync(); seteuid(o_uid); add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL); if (write_buf) free(write_buf); }
static void user_inodes_limit_test(long isoftlimit, long bsoftlimit, int user_postfix) { int ret; long i; int fd; int o_uid; struct if_dqblk s_dq, d_dq; char username[USERNAME_SZ]; snprintf(username, USERNAME_SZ, "quotauser-rank%d-%d", rank, user_postfix); add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL); getquota(QUOTAUSER, device, name2id(USER, username), &s_dq); s_dq.dqb_isoftlimit = isoftlimit; s_dq.dqb_ihardlimit = isoftlimit * 2; s_dq.dqb_bsoftlimit = bsoftlimit; s_dq.dqb_bhardlimit = bsoftlimit * 2; s_dq.dqb_curinodes = 0; s_dq.dqb_curspace = 0; setquota(QUOTAUSER, device, name2id(USER, username), s_dq); o_uid = getuid(); ret = seteuid(name2id(USER, username)); if (ret < 0) { ret = errno; abort_printf("Set euid failed:%d:%s.\n", ret, strerror(ret)); } for (i = 0; i < isoftlimit * 2; i++) { snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%ld", workplace, hostname, username, i); if (!(i % 2)) { fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE); if (fd < 0) { ret = errno; abort_printf("Open file failed:%d:%s\n", ret, strerror(ret)); } close(fd); } else mkdir(filename, FILE_MODE); getquota(QUOTAUSER, device, name2id(USER, username), &d_dq); if (d_dq.dqb_curinodes != i + 1) abort_printf("Incorrect quota stats found,expected " "inode_num = %ld,queried inode_num = %d.\n", i + 1, d_dq.dqb_curinodes); } /*We definitely should hit falure here*/ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%ld", workplace, hostname, username, isoftlimit * 2); if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) > 0) { close(fd); abort_printf("Not allowd to exceed the hard limit of inodes.\n"); } /*cleanup*/ seteuid(o_uid); for (i = 0; i < isoftlimit * 2; i++) { snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%ld", workplace, hostname, username, i); if (!(i % 2)) { ret = unlink(filename); if (ret < 0) { ret =errno; abort_printf("Failed to unlink file(%s):%d:%s\n", filename, ret, strerror(ret)); } } else { ret = rmdir(filename); if (ret < 0) { ret = errno; abort_printf("Failed to remove dir(%s):%d:%s.\n", filename, ret, strerror(ret)); } } } add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL); }
/** * @brief Convert a name to a GID * * @param[in] name The name of the user * @param[out] gid The resulting GID * @param[in] anon The anonymous GID for this export * * @return true if successful, false otherwise */ bool name2gid(const struct gsh_buffdesc *name, gid_t *gid, const gid_t anon) { return name2id(name, gid, true, anon); }
static void negative_inodes_limit_test(long isoftlimit, long bsoftlimit, long user_postfix, long rm_nums) { int ret, fd, o_uid, j; long i, file_index, rm_counts = 0; struct if_dqblk s_dq, d_dq; char username[USERNAME_SZ]; int *inodes_removed = NULL; MPI_Request request; MPI_Status status; if (!rank) { inodes_removed = (int *)malloc(sizeof(int) * isoftlimit * 2); memset((void *)inodes_removed, 0, sizeof(int) * isoftlimit *2); snprintf(username, USERNAME_SZ, "quota-user-rank%d-%ld", rank, user_postfix); add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL); getquota(QUOTAUSER, device, name2id(USER, username), &s_dq); s_dq.dqb_isoftlimit = isoftlimit; s_dq.dqb_ihardlimit = isoftlimit * 2; s_dq.dqb_bsoftlimit = bsoftlimit; s_dq.dqb_bhardlimit = bsoftlimit * 2; s_dq.dqb_curinodes = 0; s_dq.dqb_curspace = 0; setquota(QUOTAUSER, device, name2id(USER, username), s_dq); } else snprintf(username, USERNAME_SZ, "quota-user-rank0-%ld", user_postfix); /* * Rank0 creats the files,while other ranks take race to remove. * Thus,the quota number should go negative. */ if (!rank) { o_uid = getuid(); seteuid(name2id(USER, username)); for (i = 0; i < isoftlimit * 2; i++) { snprintf(filename, PATH_SZ, "%s/%s-quotafile-%ld", workplace, username, i); fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE); if (fd < 0) { ret = errno; abort_printf("Open file failed:%d:%s\n", ret, strerror(ret)); } close(fd); } seteuid(o_uid); rm_counts = 0; for (j = 1; j < size; j++) { for (i = 0; i < rm_nums; i++) { ret = MPI_Irecv(&file_index, sizeof(long), MPI_BYTE, j, 1, MPI_COMM_WORLD, &request); if (ret == MPI_SUCCESS) { rm_counts++; inodes_removed[file_index] = 1; } else abort_printf("MPI_Irecv Failed.\n"); MPI_Wait(&request, &status); } } getquota(QUOTAUSER, device, name2id(USER, username), &d_dq); if (d_dq.dqb_curinodes != isoftlimit * 2 - rm_counts) abort_printf("Negative inodes test failed among nodes," "Incorrect quota stats found,expected " "inodes_num = %ld, queried inodes_num = " "%ld.\n", isoftlimit * 2 - rm_counts, d_dq.dqb_curinodes); } else { /* * Other nodes perform a random deletion as root user */ rm_counts = 0; while (rm_counts < rm_nums) { i = get_rand(0, isoftlimit * 2 - 1); snprintf(filename, PATH_SZ, "%s/%s-quotafile-%ld", workplace, username, i); ret = unlink(filename); if (ret < 0) continue; else { ret = MPI_Isend(&i, sizeof(long), MPI_BYTE, 0, 1, MPI_COMM_WORLD, &request); if (ret != MPI_SUCCESS) abort_printf("MPI_Isend Failed.\n"); MPI_Wait(&request, &status); rm_counts++; } } } MPI_Barrier_Sync(); /* Cleanup */ if (!rank) { file_index = 0; while (file_index < isoftlimit * 2) { if (!inodes_removed[file_index]) { snprintf(filename, PATH_SZ, "%s/%s-quotafile-%ld", workplace, username, file_index); ret = unlink(filename); } file_index++; } snprintf(filename, PATH_SZ, "%s/%s-quotafile-%d", workplace, username, 0); ret = access(filename, F_OK); if (ret == 0) unlink(filename); add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL); } }
static void run_tests(void) { int i; struct if_dqblk s_dq, d_dq; char username[USERNAME_SZ], groupname[GROUPNAME_SZ]; MPI_Barrier_Sync(); root_printf("Test %d:Set/Get quota for one user/group among nodes. \n", testno); snprintf(username, USERNAME_SZ, "quotauser-%d", rank); add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL); getquota(QUOTAUSER, device, name2id(USER, username), &s_dq); s_dq.dqb_isoftlimit = 10000; s_dq.dqb_ihardlimit = 20000; s_dq.dqb_bsoftlimit = 1024 * 1024 * 10; s_dq.dqb_bhardlimit = 1024 * 1024 * 20; setquota(QUOTAUSER, device, name2id(USER, username), s_dq); getquota(QUOTAUSER, device, name2id(USER, username), &d_dq); verify_quota_items(s_dq, d_dq, ISOFT_LIMIT | IHARD_LIMIT | BSOFT_LIMIT | BHARD_LIMIT); add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL); snprintf(groupname, GROUPNAME_SZ, "quotagroup-%d", rank); add_rm_user_group(GROUPADD_BIN, ADD, GROUP, groupname, NULL); getquota(QUOTAGROUP, device, name2id(GROUP, groupname), &s_dq); s_dq.dqb_isoftlimit = 20000; s_dq.dqb_ihardlimit = 40000; s_dq.dqb_bsoftlimit = 1024 * 1024 * 10; s_dq.dqb_bhardlimit = 1024 * 1024 * 20; setquota(QUOTAGROUP, device, name2id(GROUP, groupname), s_dq); getquota(QUOTAGROUP, device, name2id(GROUP, groupname), &d_dq); verify_quota_items(s_dq, d_dq, ISOFT_LIMIT | IHARD_LIMIT | BSOFT_LIMIT | BHARD_LIMIT); add_rm_user_group(GROUPDEL_BIN, REMOVE, GROUP, groupname, NULL); testno++; MPI_Barrier_Sync(); root_printf("Test %d:Quota inodes limit test for users/groups among nodes.\n", testno); user_inodes_limit_test(100, 1024 * 1024 * 10, 1); MPI_Barrier_Sync(); group_inodes_limit_test(100, 1024 * 1024 * 10, 4, 1); testno++; MPI_Barrier_Sync(); root_printf("Test %d:Quota space limit test for users/groups among nodes.\n", testno); user_space_limit_test(100, 1024 * 256, 1); MPI_Barrier_Sync(); group_space_limit_test(100, 1024 * 256, 4, 1); testno++; MPI_Barrier_Sync(); root_printf("Test %d:Quota grace time test among nodes.\n", testno); user_inodes_grace_time_test(100, 1024 * 256, 10, 1); testno++; MPI_Barrier_Sync(); root_printf("Test %d:Huge user number test among nodes.\n", testno); for (i = 0; i < user_nums; i++) user_inodes_limit_test(100, 1024 * 1024 * 2, i); testno++; MPI_Barrier_Sync(); root_printf("Test %d:Huge group number test among nodes.\n", testno); for (i = 0; i < group_nums; i++) group_inodes_limit_test(100, 1024 * 1024 * 2, 4, i); testno++; MPI_Barrier_Sync(); root_printf("Test %d:Stress test with intensive quota operations for user/group.\n", testno); for (i = 0; i < user_nums; i++) { user_inodes_limit_test(100, 1024 * 1024, i); MPI_Barrier_Sync(); group_inodes_limit_test(100, 1024 *1024, 8, i); } testno++; MPI_Barrier_Sync(); root_printf("Test %d:Negative and positive quota test.\n", testno); negative_inodes_limit_test(100, 1024 * 1024, 1, 10); testno++; MPI_Barrier_Sync(); root_printf("Test %d:Concurrent file r/w test.\n", testno); concurrent_rw_test(100, 1024 * 1024, 1); testno++; MPI_Barrier_Sync(); root_printf("Test %d:Quota corruption test.\n", testno); quota_corrupt_test(100, 1024 * 1024, 1); testno++; }
static void concurrent_rw_test(long isoftlimit, long bsoftlimit, long user_postfix) { int ret, fd, o_uid; long i, writen_size = 0; struct if_dqblk s_dq, d_dq; char username[USERNAME_SZ]; char *write_buf; MPI_Request request; MPI_Status status; if (!rank) { snprintf(username, USERNAME_SZ, "quota-user-rank%d-%ld", rank, user_postfix); add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL); getquota(QUOTAUSER, device, name2id(USER, username), &s_dq); s_dq.dqb_isoftlimit = isoftlimit; s_dq.dqb_ihardlimit = isoftlimit * 2; s_dq.dqb_bsoftlimit = bsoftlimit; s_dq.dqb_bhardlimit = bsoftlimit * 2; s_dq.dqb_curinodes = 0; s_dq.dqb_curspace = 0; setquota(QUOTAUSER, device, name2id(USER, username), s_dq); } else snprintf(username, USERNAME_SZ, "quota-user-rank0-%ld", user_postfix); if (!rank) { o_uid = getuid(); seteuid(name2id(USER, username)); snprintf(filename, PATH_SZ, "%s/%s-quotafile", workplace, username); fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE); if (fd < 0) { ret = errno; abort_printf("Open file failed:%d:%s\n", ret, strerror(ret)); } close(fd); seteuid(o_uid); } MPI_Barrier_Sync(); if (!rank) { for (i = 1; i < size; i++) { ret = MPI_Irecv(&writen_size, sizeof(long), MPI_BYTE, i, 1, MPI_COMM_WORLD, &request); if (ret != MPI_SUCCESS) abort_printf("MPI_Irecv faile.\n"); MPI_Wait(&request, &status); printf("write_size = %ld, received.\n", writen_size); getquota(QUOTAUSER, device, name2id(USER, username), &d_dq); if (d_dq.dqb_curspace != writen_size) abort_printf("Concurrent test failed among nodes," "Incorrect space stats found, expected " "space usage = %ld, queried space usage " "= %ld.\n", writen_size, d_dq.dqb_curspace); } } else { snprintf(filename, PATH_SZ, "%s/%s-quotafile", workplace, username); fd = open(filename, O_RDWR); i = get_rand(0, rank); write_buf = (char *)malloc(clustersize * i); memset(write_buf, 0, clustersize * i); writen_size = pwrite(fd, write_buf, clustersize * i, 0); if (writen_size < 0) { ret = errno; abort_printf("pwrite failed:%d:%s.\n", ret, strerror(ret)); } printf("write_size = %ld, sent.\n", writen_size); ret = MPI_Isend(&writen_size, sizeof(long), MPI_BYTE, 0, 1, MPI_COMM_WORLD, &request); if (ret != MPI_SUCCESS) abort_printf("MPI_Isend failed.\n"); MPI_Wait(&request, &status); } MPI_Barrier_Sync(); if(!rank) { ret = unlink(filename); if (ret < 0) { ret = errno; abort_printf("Unlink file failed:%d:%s\n", ret, strerror(ret)); } add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL); } }
static void quota_corrupt_test(long isoftlimit, long bsoftlimit, int user_postfix) { int ret, fd; long i; int o_uid; struct if_dqblk s_dq, d_dq; char username[USERNAME_SZ]; snprintf(username, USERNAME_SZ, "quotauser-rank%d-%d", rank, user_postfix); add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL); getquota(QUOTAUSER, device, name2id(USER, username), &s_dq); s_dq.dqb_isoftlimit = isoftlimit; s_dq.dqb_ihardlimit = isoftlimit * 2; s_dq.dqb_bsoftlimit = bsoftlimit; s_dq.dqb_bhardlimit = bsoftlimit * 2; s_dq.dqb_curinodes = 0xFFFFFFFFFFFFFFFF; s_dq.dqb_curspace = 0xFFFFFFFFFFFFFFFF; setquota(QUOTAUSER, device, name2id(USER, username), s_dq); o_uid = getuid(); ret = seteuid(name2id(USER, username)); for (i = 0; i < isoftlimit; i++) { snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%ld", workplace, hostname, username, i); fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE); if (fd < 0) { ret = errno; abort_printf("Open file failed:%d:%s\n", ret, strerror(ret)); } close(fd); } /* * After a while, we check if the curinodes and curspace * get synced to be correct. */ sleep(5); seteuid(o_uid); getquota(QUOTAUSER, device, name2id(USER, username), &d_dq); if (d_dq.dqb_curinodes != isoftlimit) abort_printf("Quota corrupt test failed.expected inode_nums = " "%ld, while queried inode_nums = %ld.\n", isoftlimit, d_dq.dqb_curinodes); for (i = 0; i < isoftlimit; i++) { snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%ld", workplace, hostname, username, i); ret = unlink(filename); if (ret < 0) { ret = errno; abort_printf("Unlink file %s failed:%d:%s.\n", filename, ret, strerror(ret)); } } add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL); }