gid_t_rec * gid_t_cache::cache(const uid_t uid, const gid_t gid) { int rv; char buf[4096]; struct passwd pwd; struct passwd *pwdrv; gid_t_rec *rec; rec = allocrec(); rec->uid = uid; rv = ::getpwuid_r(uid,&pwd,buf,sizeof(buf),&pwdrv); if(pwdrv != NULL && rv == 0) { rec->size = 0; ::getgrouplist(pwd.pw_name,gid,NULL,&rec->size); rec->size = std::min(MAXGIDS,rec->size); rv = ::getgrouplist(pwd.pw_name,gid,rec->gids,&rec->size); if(rv == -1) { rec->gids[0] = gid; rec->size = 1; } } return rec; }
static void merge_sort_fstack(FILE *outfp, put_func_t put, struct field *ftbl) { struct mfile *flistb[MERGE_FNUM], **flist = flistb, *cfile; RECHEADER *new_rec; u_char *new_end; void *tmp; int c, i, nfiles; size_t sz; /* Read one record from each file (read again if a duplicate) */ for (nfiles = i = 0; i < fstack_count; i++) { cfile = &fstack[i]; if (cfile->rec == NULL) { cfile->rec = allocrec(NULL, DEFLLEN); cfile->end = (u_char *)cfile->rec + DEFLLEN; } rewind(cfile->fp); for (;;) { c = cfile->get(cfile->fp, cfile->rec, cfile->end, ftbl); if (c == EOF) break; if (c == BUFFEND) { /* Double buffer size */ sz = (cfile->end - (u_char *)cfile->rec) * 2; cfile->rec = allocrec(cfile->rec, sz); cfile->end = (u_char *)cfile->rec + sz; continue; } if (nfiles != 0) { if (insert(flist, cfile, nfiles, !DELETE)) /* Duplicate removed */ continue; } else flist[0] = cfile; nfiles++; break; } } if (nfiles == 0) return; /* * We now loop reading a new record from the file with the * 'sorted first' existing record. * As each record is added, the 'first' record is written to the * output file - maintaining one record from each file in the sorted * list. */ new_rec = allocrec(NULL, DEFLLEN); new_end = (u_char *)new_rec + DEFLLEN; for (;;) { cfile = flist[0]; c = cfile->get(cfile->fp, new_rec, new_end, ftbl); if (c == EOF) { /* Write out last record from now-empty input */ put(cfile->rec, outfp); if (--nfiles == 0) break; /* Replace from file with now-first sorted record. */ /* (Moving base 'flist' saves copying everything!) */ flist++; continue; } if (c == BUFFEND) { /* Buffer not large enough - double in size */ sz = (new_end - (u_char *)new_rec) * 2; new_rec = allocrec(new_rec, sz); new_end = (u_char *)new_rec +sz; continue; } /* Swap in new buffer, saving old */ tmp = cfile->rec; cfile->rec = new_rec; new_rec = tmp; tmp = cfile->end; cfile->end = new_end; new_end = tmp; /* Add into sort, removing the original first entry */ c = insert(flist, cfile, nfiles, DELETE); if (c != 0 || (UNIQUE && cfile == flist[0] && cmp(new_rec, cfile->rec) == 0)) { /* Was an unwanted duplicate, restore buffer */ tmp = cfile->rec; cfile->rec = new_rec; new_rec = tmp; tmp = cfile->end; cfile->end = new_end; new_end = tmp; continue; } /* Write out 'old' record */ put(new_rec, outfp); } free(new_rec); }
void fsort(struct filelist *filelist, int nfiles, FILE *outfp, struct field *ftbl) { RECHEADER **keylist; RECHEADER **keypos, **keyp; RECHEADER *buffer; size_t bufsize = DEFBUFSIZE; u_char *bufend; int mfct = 0; int c, nelem; get_func_t get; RECHEADER *crec; RECHEADER *nbuffer; FILE *fp, *tmp_fp; int file_no; int max_recs = DEBUG('m') ? 16 : MAXNUM; buffer = allocrec(NULL, bufsize); bufend = (u_char *)buffer + bufsize; /* Allocate double length keymap for radix_sort */ keylist = malloc(2 * max_recs * sizeof(*keylist)); if (buffer == NULL || keylist == NULL) err(2, "failed to malloc initial buffer or keylist"); if (SINGL_FLD) /* Key and data are one! */ get = makeline; else /* Key (merged key fields) added before data */ get = makekey; file_no = 0; fp = fopen(filelist->names[0], "r"); if (fp == NULL) err(2, "%s", filelist->names[0]); /* Loop through reads of chunk of input files that get sorted * and then merged together. */ for (;;) { keypos = keylist; nelem = 0; crec = buffer; makeline_copydown(crec); /* Loop reading records */ for (;;) { c = get(fp, crec, bufend, ftbl); /* 'c' is 0, EOF or BUFFEND */ if (c == 0) { /* Save start of key in input buffer */ *keypos++ = crec; if (++nelem == max_recs) { c = BUFFEND; break; } crec = (RECHEADER *)(crec->data + SALIGN(crec->length)); continue; } if (c == EOF) { /* try next file */ if (++file_no >= nfiles) /* no more files */ break; fp = fopen(filelist->names[file_no], "r"); if (fp == NULL) err(2, "%s", filelist->names[file_no]); continue; } if (nelem >= max_recs || (bufsize >= MAXBUFSIZE && nelem > 8)) /* Need to sort and save this lot of data */ break; /* c == BUFFEND, and we can process more data */ /* Allocate a larger buffer for this lot of data */ bufsize *= 2; nbuffer = allocrec(buffer, bufsize); if (!nbuffer) { err(2, "failed to realloc buffer to %zu bytes", bufsize); } /* patch up keylist[] */ for (keyp = &keypos[-1]; keyp >= keylist; keyp--) *keyp = nbuffer + (*keyp - buffer); crec = nbuffer + (crec - buffer); buffer = nbuffer; bufend = (u_char *)buffer + bufsize; } /* Sort this set of records */ radix_sort(keylist, keylist + max_recs, nelem); if (c == EOF && mfct == 0) { /* all the data is (sorted) in the buffer */ append(keylist, nelem, outfp, DEBUG('k') ? putkeydump : putline); break; } /* Save current data to a temporary file for a later merge */ if (nelem != 0) { tmp_fp = ftmp(); append(keylist, nelem, tmp_fp, putrec); save_for_merge(tmp_fp, geteasy, ftbl); } mfct = 1; if (c == EOF) { /* merge to output file */ merge_sort(outfp, DEBUG('k') ? putkeydump : putline, ftbl); break; } } free(keylist); keylist = NULL; free(buffer); buffer = NULL; }