/* * Push down to new source of characters. * If fd>0 and str==NULL, then from a file `name'; * if fd==-1 and str, then from the string. */ Source * setsource(char *name, int fd, char *str) { Source *s = new(Source); int len; s->line = 1; s->lineinc = 0; s->fd = fd; s->filename = name; s->next = cursource; s->ifdepth = 0; cursource = s; /* slop at right for EOB */ if (str) { len = strlen(str); s->inb = domalloc(len+4); s->inp = s->inb; strncpy((char *)s->inp, str, len); } else { s->inb = domalloc(INS+4); s->inp = s->inb; len = 0; } s->inl = s->inp+len; s->inl[0] = s->inl[1] = EOB; return s; }
void iniths(void) { hidesets = (Hideset *)domalloc(maxhidesets*sizeof(Hideset *)); hidesets[0] = (Hideset)domalloc(sizeof *hidesets[0]); *hidesets[0] = NULL; nhidesets++; }
static void bitmap_init(uint32_t bitblocks) { size_t i, mapsize = bitblocks * SFS_BLOCKSIZE; bitmapdata = domalloc(mapsize * sizeof(uint8_t)); tofreedata = domalloc(mapsize * sizeof(uint8_t)); for (i=0; i<mapsize; i++) { bitmapdata[i] = tofreedata[i] = 0; } }
static void addmemory(uint32_t ino, uint32_t linkcount) { assert(ninodes <= maxinodes); if (ninodes == maxinodes) { #ifdef NO_REALLOC int newmax = (maxinodes+1)*2; void *p = domalloc(newmax * sizeof(struct inodememory)); if (inodes) { memcpy(p, inodes, ninodes); free(inodes); } inodes = p; #else maxinodes = (maxinodes+1)*2; inodes = realloc(inodes, maxinodes * sizeof(uint32_t)); if (inodes==NULL) { errx(EXIT_FATAL, "Out of memory"); } #endif } inodes[ninodes].ino = ino; inodes[ninodes].linkcount = linkcount; }
static void * serial_init(int slot, int argc, char *argv[]) { struct ser_data *sd = domalloc(sizeof(struct ser_data)); sd->sd_slot = slot; sd->sd_wbusy = 0; sd->sd_rbusy = 0; sd->sd_rirq.si_on = 0; sd->sd_rirq.si_ready = 0; sd->sd_rirq.si_force = 0; sd->sd_wirq.si_on = 0; sd->sd_wirq.si_ready = 0; sd->sd_wirq.si_force = 0; sd->sd_readch = 0; sd->sd_didread = 1; sd->sd_droppedreads = 0; sd->sd_inbufhead = 0; /* empty if head==tail */ sd->sd_inbuftail = 0; (void)argc; (void)argv; console_onkey(sd, serial_input); return sd; }
/* * Return the (possibly new) hideset obtained by adding np to hs. */ int newhideset(int hs, Nlist *np) { int i, len; Nlist *nhs[HSSIZ+3]; Hideset hs1, hs2; len = inserths(nhs, hidesets[hs], np); for (i=0; i<nhidesets; i++) { for (hs1=nhs, hs2=hidesets[i]; *hs1==*hs2; hs1++, hs2++) if (*hs1 == NULL) return i; } if (len>=HSSIZ) return hs; if (nhidesets >= maxhidesets) { maxhidesets = 3*maxhidesets/2+1; hidesets = (Hideset *)realloc(hidesets, (sizeof (Hideset *))*maxhidesets); if (hidesets == NULL) error(FATAL, "Out of memory from realloc"); } hs1 = (Hideset)domalloc(len*sizeof *hs1); memmove(hs1, nhs, len*sizeof *hs1); hidesets[nhidesets] = hs1; return nhidesets++; }
static struct placefile * placefile_create(const struct place *from, const char *name, bool fromsystemdir) { struct placefile *pf; const char *s; size_t len; pf = domalloc(sizeof(*pf)); pf->includedfrom = *from; s = strrchr(name, '/'); len = (s == NULL) ? 0 : s - name; pf->dir = dostrndup(name, len); pf->name = dostrdup(name); pf->fromsystemdir = fromsystemdir; if (from->file != NULL) { pf->depth = from->file->depth + 1; } else { pf->depth = 1; } return pf; }
/* * allocate and initialize a new string from s, of length l, at offset o * Null terminated. */ uchar * newstring(uchar *s, int l, int o) { uchar *ns = (uchar *)domalloc(l+o+1); ns[l+o] = '\0'; return (uchar*)strncpy((char*)ns+o, (char*)s, l) - o; }
static void lamebus_commonmainboard_init(int isold, int slot, int argc, char *argv[]) { int i; unsigned long j, tmp_ncpus, ncores; const char *myname = isold ? "oldmainboard" : "mainboard"; Assert(slot==LAMEBUS_CONTROLLER_SLOT); /* * Defaults */ bus_ramsize = 0; /* for now require configuration */ tmp_ncpus = 1; ncores = 1; for (i=1; i<argc; i++) { if (!strncmp(argv[i], "ramsize=", 8)) { bus_ramsize = getsize(argv[i]+8); } else if (!isold && !strncmp(argv[i], "cpus=", 5)) { tmp_ncpus = strtoul(argv[i]+5, NULL, 0); } else if (!isold && !strncmp(argv[i], "cores=", 6)) { ncores = strtoul(argv[i]+6, NULL, 0); } else { msg("%s: invalid option `%s'", myname, argv[i]); die(); } } if (tmp_ncpus == 0 || ncores == 0) { msg("%s: give me no CPUs and I'll give you no lies", myname); die(); } if (ncores > 1) { msg("%s: no support for multicore CPUs yet", myname); die(); } if (tmp_ncpus > 32) { msg("%s: too many CPUs", myname); die(); } /* avoid overflow from unsigned long to unsigned */ ncpus = tmp_ncpus; for (j=0; j<ncpus; j++) { cpus[j].cpu_enabled = 0; cpus[j].cpu_enabled_interrupts = 0xffffffff; cpus[j].cpu_ipi = 0; cpus[j].cpu_interrupting = 0; cpus[j].cpu_cram = domalloc(LAMEBUS_CRAM_SIZE); } cpus[0].cpu_enabled = 1; }
/** * setobjname - 设定目标文件名(xx.c -> xx.o) * @f: c源程序名 * "xx.o" 存储在全局变量objname中 */ void setobjname(char *f) { int n = strlen(f); objname = (char*) domalloc(n + 5); strcpy(objname, f); if (objname[n - 2] == '.') { /* 如果是filename.c */ strcpy(objname + n - 1, "o: "); /* 则变成filename.o */ } else { /* 如果是filename(没有扩展名...) */ strcpy(objname + n, "obj: "); } }
char * dostrndup(const char *s, size_t len) { char *ret; ret = domalloc(len+1); memcpy(ret, s, len); ret[len] = '\0'; return ret; }
void setobjname(char* f) { int n = strlen(f); objname = (char*)domalloc(n + 5); strcpy(objname, f); if (objname[n - 2] == '.') { strcpy(objname + n - 1, "$O: "); } else { strcpy(objname + n, "$O: "); } }
void maketokenrow(int size, Tokenrow *trp) { trp->max = size; if (size>0) trp->bp = (Token *)domalloc(size*sizeof(Token)); else trp->bp = NULL; trp->tp = trp->bp; trp->lp = trp->bp; }
/* * Expand the macro whose name is np, at token trp->tp, in the tokenrow. * Return trp->tp at the first token next to be expanded * (ordinarily the beginning of the expansion) */ void expand(Tokenrow *trp, Nlist *np) { Tokenrow ntr; int ntokc, narg, i; Token *tp; int hs; #ifdef __ORCAC__ Tokenrow **atr; atr = domalloc(sizeof(Tokenrow *) * (NARG+1)); #define RETURN free(atr);return #else Tokenrow *atr[NARG+1]; #define RETURN return; #endif copytokenrow(&ntr, np->vp); /* copy macro value */ if (np->ap==NULL) /* parameterless */ ntokc = 1; else { ntokc = gatherargs(trp, atr, &narg); if (narg<0) { /* not actually a call (no '(') */ trp->tp++; RETURN; } if (narg != rowlen(np->ap)) { error(ERROR, "Disagreement in number of macro arguments"); trp->tp->hideset = newhideset(trp->tp->hideset, np); trp->tp += ntokc; RETURN; } substargs(np, &ntr, atr); /* put args into replacement */ for (i=0; i<narg; i++) { dofree(atr[i]->bp); dofree(atr[i]); } } doconcat(&ntr); /* execute ## operators */ hs = newhideset(trp->tp->hideset, np); for (tp=ntr.bp; tp<ntr.lp; tp++) { /* distribute hidesets */ if (tp->type==NAME) { if (tp->hideset==0) tp->hideset = hs; else tp->hideset = unionhideset(tp->hideset, hs); } } ntr.tp = ntr.bp; insertrow(trp, ntokc, &ntr); trp->tp -= rowlen(&ntr); dofree(ntr.bp); RETURN; }
char * dostrdup(const char *s) { char *ret; size_t len; len = strlen(s); ret = domalloc(len+1); strcpy(ret, s); return ret; }
/* * Push down to new source of characters. * If fd>0 and str==NULL, then from a file `name'; * if fd==-1 and str, then from the string. */ Source * setsource(char *name, int fd, char *str) { Source *s = new(Source); int len; s->line = 1; s->lineinc = 0; s->fd = fd; s->filename = name; s->next = cursource; s->ifdepth = 0; cursource = s; /* slop at right for EOB */ if (str) { len = strlen(str); s->inb = domalloc(len+4); s->inp = s->inb; strncpy((char *)s->inp, str, len); } else { Dir *d; int junk; ulong length = 0; d = dirfstat(fd); if (d != nil) { length = d->length; free(d); } junk = length; if (junk<INS) junk = INS; s->inb = domalloc((junk)+4); s->inp = s->inb; len = 0; } s->ins = INS; s->inl = s->inp+len; s->inl[0] = s->inl[1] = EOB; return s; }
static void commandline_addfile(const struct place *p, char *name, bool suppress_output) { struct commandline_file *cf; cf = domalloc(sizeof(*cf)); cf->where = *p; cf->name = name; cf->suppress_output = suppress_output; array_add(&commandline_files, cf, NULL); }
char * dostrdup2(const char *s, const char *t) { char *ret; size_t len; len = strlen(s) + strlen(t); ret = domalloc(len+1); strcpy(ret, s); strcat(ret, t); return ret; }
/* * Push down to new source of characters. * If fd>0 and str==NULL, then from a file `name'; * if fd==-1 and str, then from the string. */ Source * setsource(char *name, int path, int fd, char const *str, int wrap) { Source *s = new(Source); size_t len; s->line = 1; s->lineinc = 0; s->fd = fd; s->filename = name; s->next = cursource; s->ifdepth = 0; s->pathdepth = path; s->wrap = wrap; cursource = s; if (s->wrap) genwrap(0); /* slop at right for EOB */ if (str) { len = strlen(str); s->inb = domalloc(len + 4); s->inp = s->inb; memcpy((char *) s->inp, str, len); } else { s->inb = domalloc(INS + 4); s->inp = s->inb; len = 0; } s->inl = s->inp + len; s->inl[0] = s->inl[1] = EOB; return s; }
static void initstats(unsigned ncpus) { unsigned i; g_stats.s_percpu = domalloc(ncpus * sizeof(*g_stats.s_percpu)); g_stats.s_numcpus = ncpus; for (i=0; i<ncpus; i++) { g_stats.s_percpu[i].sp_kcycles = 0; g_stats.s_percpu[i].sp_ucycles = 0; g_stats.s_percpu[i].sp_icycles = 0; } }
static void commandline_macro_add(const struct place *p, const char *macro, const struct place *p2, const char *expansion) { struct commandline_macro *cm; cm = domalloc(sizeof(*cm)); cm->where = *p; cm->where2 = *p2; cm->macro = macro; cm->expansion = expansion; array_add(&commandline_macros, cm, NULL); }
static void debug_write_mem(struct gdbcontext *ctx, const char *spec) { uint32_t vaddr, length, i; uint8_t *bytes; const char *curptr; // AAAAAAA,LLL:DDDD // address,len,data vaddr = strtoul(spec, (char **) &curptr, 16); length = strtoul(curptr + 1, (char **)&curptr, 16); // curptr now points to the ':' which // delimits the length from the data // so we advance it a little curptr++; bytes = domalloc(length); for (i=0; i<length; i++) { bytes[i] = hexbyte(curptr, (char **) &curptr); } for (i=0; i<length && (vaddr+i)%4 != 0; i++) { if (cpudebug_store_byte(debug_cpu, vaddr+i, bytes[i])) { debug_send(ctx, "E03"); return; } } for (; i+4<=length; i+=4) { uint32_t word; memcpy(&word, bytes+i, sizeof(uint32_t)); if (cpudebug_store_word(debug_cpu, vaddr+i, ntohl(word))) { debug_send(ctx, "E03"); return; } } for (; i<length; i++) { if (cpudebug_store_byte(debug_cpu, vaddr+i, bytes[i])) { debug_send(ctx, "E03"); return; } } free(bytes); debug_send(ctx, "OK"); }
/* * Wrapper around realloc. OSZ is the old block size, which we need if * we're going to emulate realloc with malloc. */ void * dorealloc(void *op, size_t osz, size_t nsz) { void *np; #ifdef NO_REALLOC size_t copysz; np = domalloc(nsz); if (op != NULL) { copysz = osz < nsz ? osz : nsz; memcpy(np, op, copysz); free(op); } #else (void)osz; np = realloc(op, nsz); if (np == NULL) { errx(EXIT_FATAL, "Out of memory"); } #endif return np; }
void suidaccept::dispatch (svccb *sbp) { if (sbp) { const authunix_parms *aup = sbp->getaup (); if (!aup) { warn ("suidserv: ignoring SETUID message with no auth\n"); sbp->reject (AUTH_REJECTEDCRED); } #ifdef HAVE_GETPEEREID else if (uid && (implicit_cast<u_int32_t> (uid) != implicit_cast<u_int32_t> (aup->aup_uid))) { warn ("suidserv: rejected connection from UID %u claiming to be %u\n", uid, aup->aup_uid); sbp->reject (AUTH_REJECTEDVERF); } #endif /* HAVE_GETPEEREID */ else { authunix_parms au = *aup; if (aup->aup_machname) au.aup_machname = xstrdup (aup->aup_machname); domalloc (au.aup_gids, aup->aup_len * sizeof (aup->aup_gids[0])); memcpy (au.aup_gids, aup->aup_gids, aup->aup_len * sizeof (aup->aup_gids[0])); sbp->replyref (0); as->setcb (NULL); as = NULL; (*cb) (ax, &au); ax = NULL; xfree (au.aup_machname); xfree (au.aup_gids); delete this; return; } } as->setcb (NULL); delete this; }
static int compute_sectors(struct disk_data *dd) { uint32_t physsectors; // total number of actual sectors //uint32_t sectorspertrack; // average sectors per track uint32_t i, tot; double sectors_per_area; double trackwidth; /* * Compute number of physical sectors. We use a bit more than the * requested space so as to leave room for sector remapping. Not * that we actually do sector remapping when computing latencies, * but we could. Note that these spare sectors do not appear in * the file we use for underlying storage. */ physsectors = (uint32_t)(dd->dd_totsectors * SECTOR_FUDGE); if (physsectors < dd->dd_totsectors) { /* Overflow - didn't fit in uint32_t */ smoke("Fatal error computing disk geometry"); return -1; } //sectorspertrack = physsectors/NUMTRACKS; dd->dd_tracks = NUMTRACKS; /* allocate space for dd_tracks entries */ dd->dd_sectors = domalloc(dd->dd_tracks*sizeof(uint32_t)); /* compute the width of each track */ trackwidth = ((OUTER_DIAM - INNER_DIAM)/2) / (double)dd->dd_tracks; /* compute the number of sectors per unit area of disk */ sectors_per_area = physsectors / (PLATTER_AREA); /* * Now, figure out how many sectors are on each track. * We do this by computing the area of the track and multiplying * by sectors_per_area, truncating to the next smallest integer. * We reserve one sector on each track. */ for (i=0; i<dd->dd_tracks; i++) { double inside = INNER_DIAM/2.0 + i*trackwidth; double outside = inside + trackwidth; /* * this track's area = pi*(outside^2 - inside^2) = pi*(outside + * inside)*(outside - inside) = pi*(outside + * inside)*(trackwidth) */ double trackarea = (outside+inside)*trackwidth*PI; double sectors = sectors_per_area*trackarea; if (sectors < 2.0) { /* too small */ msg("disk: slot %d: track %u has only one sector", dd->dd_slot, i); return -1; } dd->dd_sectors[i] = ((int)sectors) - 1; } /* Now compute the total number of sectors available. */ tot = 0; for (i=0; i<dd->dd_tracks; i++) { tot += dd->dd_sectors[i]; } /* Make sure we've got enough space. */ if (tot < dd->dd_totsectors) { /* * Shouldn't happen. If it does, increase SECTOR_FUDGE. */ msg("disk: slot %d: Not enough SECTOR_FUDGE", dd->dd_slot); return -1; } return 0; }
static void * disk_init(int slot, int argc, char *argv[]) { struct disk_data *dd; const char *filename = NULL; off_t size; uint32_t totsectors=0; uint32_t rpm = 3600; int i, paranoid=0, usedoom = 1; for (i=1; i<argc; i++) { if (!strncmp(argv[i], "rpm=", 4)) { rpm = atoi(argv[i]+4); } else if (!strncmp(argv[i], "sectors=", 8)) { totsectors = atoi(argv[i]+8); } else if (!strncmp(argv[i], "size=", 5)) { size = getsize(argv[i]+5); if (size % SECTSIZE) { msg("disk: slot %d: Configured size is not a " "unit number of sectors", slot); die(); } totsectors = size / SECTSIZE; } else if (!strncmp(argv[i], "file=", 5)) { filename = argv[i]+5; } else if (!strcmp(argv[i], "paranoid")) { paranoid = 1; } else if (!strcmp(argv[i], "doom")) { usedoom = 1; } else if (!strcmp(argv[i], "nodoom")) { usedoom = 0; } else { msg("disk: slot %d: invalid option %s", slot, argv[i]); die(); } } if (rpm < 60) { msg("disk: slot %d: RPM too low (%d)", slot, rpm); die(); } if (rpm % 60) { msg("disk: slot %d: RPM %d not a multiple of 60", slot, rpm); die(); } if (filename==NULL) { msg("disk: slot %d: No filename specified", slot); die(); } /* * Set up the disk */ dd = domalloc(sizeof(struct disk_data)); dd->dd_slot = slot; dd->dd_fd = -1; dd->dd_paranoid = paranoid; dd->dd_sectors = NULL; dd->dd_tracks = 0; dd->dd_totsectors = 0; dd->dd_rpm = rpm; dd->dd_nsecs_per_rev = 1000000000 / (dd->dd_rpm / 60); dd->dd_usedoom = usedoom; dd->dd_current_track = 0; clock_time(&dd->dd_trackarrival_secs, &dd->dd_trackarrival_nsecs); dd->dd_iostatus = -1; dd->dd_timedop = 0; dd->dd_worktries = 0; dd->dd_stat = DISKSTAT_IDLE; dd->dd_sect = 0; dd->dd_buf = domalloc(SECTSIZE); disk_open(dd, filename, totsectors); if (dd->dd_totsectors != totsectors && totsectors > 0) { msg("disk: slot %d: %s: Wrong configured size %u (%uK)", slot, filename, totsectors, totsectors * 1024 / SECTSIZE); msg("disk: slot %d: %s: Using image size %u (%uK)", slot, filename, dd->dd_totsectors, dd->dd_totsectors * 1024 / SECTSIZE); } if (dd->dd_totsectors < 128) { msg("disk: slot %d: %s: Too small", slot, filename); die(); } /* set dd_cylinders, dd_sectors, dd_heads */ if (compute_sectors(dd)) { msg("disk: slot %d: %s: Geometry initialization failed " "(try another size)", slot, filename); die(); } return dd; }
/* * Process a directory. INO is the inode number; PARENTINO is the * parent's inode number; PATHSOFAR is the path to this directory. * * Recursively checks its subdirs. * * In the FUTURE we might want to improve the handling of crosslinked * directories so it picks the parent that the .. entry points to, * instead of the first entry we recursively find. Beware of course * that the .. entry might not point to anywhere valid at all... */ static int pass2_dir(uint32_t ino, uint32_t parentino, const char *pathsofar) { struct sfs_dinode sfi; struct sfs_dir *direntries; int *sortvector; uint32_t dirsize, ndirentries, maxdirentries, subdircount, i; int ichanged=0, dchanged=0, dotseen=0, dotdotseen=0; if (inode_visitdir(ino)) { /* crosslinked dir; tell parent to remove the entry */ return 1; } /* Load the inode. */ sfs_readinode(ino, &sfi); /* * Load the directory. If there is any leftover room in the * last block, allocate space for it in case we want to insert * entries. */ ndirentries = sfi.sfi_size/sizeof(struct sfs_dir); maxdirentries = SFS_ROUNDUP(ndirentries, SFS_BLOCKSIZE/sizeof(struct sfs_dir)); dirsize = maxdirentries * sizeof(struct sfs_dir); direntries = domalloc(dirsize); sortvector = domalloc(ndirentries * sizeof(int)); sfs_readdir(&sfi, direntries, ndirentries); for (i=ndirentries; i<maxdirentries; i++) { direntries[i].sfd_ino = SFS_NOINO; bzero(direntries[i].sfd_name, sizeof(direntries[i].sfd_name)); } /* * Sort by name and check for duplicate names. */ sfsdir_sort(direntries, ndirentries, sortvector); /* don't use ndirentries-1 here, in case ndirentries == 0 */ for (i=0; i+1<ndirentries; i++) { struct sfs_dir *d1 = &direntries[sortvector[i]]; struct sfs_dir *d2 = &direntries[sortvector[i+1]]; assert(d1 != d2); if (d1->sfd_ino == SFS_NOINO || d2->sfd_ino == SFS_NOINO) { /* sfsdir_sort puts these last */ continue; } if (!strcmp(d1->sfd_name, d2->sfd_name)) { if (d1->sfd_ino == d2->sfd_ino) { setbadness(EXIT_RECOV); warnx("Directory %s: Duplicate entries for " "%s (merged)", pathsofar, d1->sfd_name); d1->sfd_ino = SFS_NOINO; d1->sfd_name[0] = 0; } else { /* XXX: what if FSCK.n.m already exists? */ snprintf(d1->sfd_name, sizeof(d1->sfd_name), "FSCK.%lu.%lu", (unsigned long) d1->sfd_ino, (unsigned long) uniqueid()); setbadness(EXIT_RECOV); warnx("Directory %s: Duplicate names %s " "(one renamed: %s)", pathsofar, d2->sfd_name, d1->sfd_name); } dchanged = 1; } } /* * Look for the . and .. entries. */ for (i=0; i<ndirentries; i++) { if (!strcmp(direntries[i].sfd_name, ".")) { if (direntries[i].sfd_ino != ino) { setbadness(EXIT_RECOV); warnx("Directory %s: Incorrect `.' entry " "(fixed)", pathsofar); direntries[i].sfd_ino = ino; dchanged = 1; } /* duplicates are checked above -> only one . here */ assert(dotseen==0); dotseen = 1; } else if (!strcmp(direntries[i].sfd_name, "..")) { if (direntries[i].sfd_ino != parentino) { setbadness(EXIT_RECOV); warnx("Directory %s: Incorrect `..' entry " "(fixed)", pathsofar); direntries[i].sfd_ino = parentino; dchanged = 1; } /* duplicates are checked above -> only one .. here */ assert(dotdotseen==0); dotdotseen = 1; } } /* * If no . entry, try to insert one. */ if (!dotseen) { if (sfsdir_tryadd(direntries, ndirentries, ".", ino)==0) { setbadness(EXIT_RECOV); warnx("Directory %s: No `.' entry (added)", pathsofar); dchanged = 1; } else if (sfsdir_tryadd(direntries, maxdirentries, ".", ino)==0) { setbadness(EXIT_RECOV); warnx("Directory %s: No `.' entry (added)", pathsofar); ndirentries++; dchanged = 1; sfi.sfi_size += sizeof(struct sfs_dir); ichanged = 1; } else { setbadness(EXIT_UNRECOV); warnx("Directory %s: No `.' entry (NOT FIXED)", pathsofar); } } /* * If no .. entry, try to insert one. */ if (!dotdotseen) { if (sfsdir_tryadd(direntries, ndirentries, "..", parentino)==0) { setbadness(EXIT_RECOV); warnx("Directory %s: No `..' entry (added)", pathsofar); dchanged = 1; } else if (sfsdir_tryadd(direntries, maxdirentries, "..", parentino)==0) { setbadness(EXIT_RECOV); warnx("Directory %s: No `..' entry (added)", pathsofar); ndirentries++; dchanged = 1; sfi.sfi_size += sizeof(struct sfs_dir); ichanged = 1; } else { setbadness(EXIT_UNRECOV); warnx("Directory %s: No `..' entry (NOT FIXED)", pathsofar); } } /* * Now load each inode in the directory. * * For regular files, count the number of links we see; for * directories, recurse. Count the number of subdirs seen * so we can correct our own link count if necessary. */ subdircount=0; for (i=0; i<ndirentries; i++) { if (direntries[i].sfd_ino == SFS_NOINO) { /* nothing */ } else if (!strcmp(direntries[i].sfd_name, ".")) { /* nothing */ } else if (!strcmp(direntries[i].sfd_name, "..")) { /* nothing */ } else { char path[strlen(pathsofar)+SFS_NAMELEN+1]; struct sfs_dinode subsfi; sfs_readinode(direntries[i].sfd_ino, &subsfi); snprintf(path, sizeof(path), "%s/%s", pathsofar, direntries[i].sfd_name); switch (subsfi.sfi_type) { case SFS_TYPE_FILE: inode_addlink(direntries[i].sfd_ino); break; case SFS_TYPE_DIR: if (pass2_dir(direntries[i].sfd_ino, ino, path)) { setbadness(EXIT_RECOV); warnx("Directory %s: Crosslink to " "other directory (removed)", path); direntries[i].sfd_ino = SFS_NOINO; direntries[i].sfd_name[0] = 0; dchanged = 1; } else { subdircount++; } break; default: setbadness(EXIT_RECOV); warnx("Object %s: Invalid inode type " "(removed)", path); direntries[i].sfd_ino = SFS_NOINO; direntries[i].sfd_name[0] = 0; dchanged = 1; break; } } } /* * Fix up the link count if needed. */ if (sfi.sfi_linkcount != subdircount+2) { setbadness(EXIT_RECOV); warnx("Directory %s: Link count %lu should be %lu (fixed)", pathsofar, (unsigned long) sfi.sfi_linkcount, (unsigned long) subdircount+2); sfi.sfi_linkcount = subdircount+2; ichanged = 1; } /* * Write back anything that changed, clean up, and return. */ if (dchanged) { sfs_writedir(&sfi, direntries, ndirentries); } if (ichanged) { sfs_writeinode(ino, &sfi); } free(direntries); free(sortvector); return 0; }
static int check_dir(uint32_t ino, uint32_t parentino, const char *pathsofar) { struct sfs_inode sfi; struct sfs_dir *direntries; int *sortvector; uint32_t dirsize, ndirentries, maxdirentries, subdircount, i; int ichanged=0, dchanged=0, dotseen=0, dotdotseen=0; diskread(&sfi, ino); swapinode(&sfi); if (remember_dir(ino, pathsofar)) { /* crosslinked dir */ return 1; } bitmap_mark(ino, B_INODE, ino); count_dirs++; if (sfi.sfi_size % sizeof(struct sfs_dir) != 0) { setbadness(EXIT_RECOV); warnx("Directory /%s has illegal size %lu (fixed)", pathsofar, (unsigned long) sfi.sfi_size); sfi.sfi_size = SFS_ROUNDUP(sfi.sfi_size, sizeof(struct sfs_dir)); ichanged = 1; } if (check_inode_blocks(ino, &sfi, 1)) { ichanged = 1; } ndirentries = sfi.sfi_size/sizeof(struct sfs_dir); maxdirentries = SFS_ROUNDUP(ndirentries, SFS_BLOCKSIZE/sizeof(struct sfs_dir)); dirsize = maxdirentries * sizeof(struct sfs_dir); direntries = domalloc(dirsize); sortvector = domalloc(ndirentries * sizeof(int)); dirread(&sfi, direntries, ndirentries); for (i=ndirentries; i<maxdirentries; i++) { direntries[i].sfd_ino = SFS_NOINO; bzero(direntries[i].sfd_name, sizeof(direntries[i].sfd_name)); } for (i=0; i<ndirentries; i++) { if (check_dir_entry(pathsofar, i, &direntries[i])) { dchanged = 1; } sortvector[i] = i; } sortdir(sortvector, direntries, ndirentries); /* don't use ndirentries-1 here in case ndirentries == 0 */ for (i=0; i+1<ndirentries; i++) { struct sfs_dir *d1 = &direntries[sortvector[i]]; struct sfs_dir *d2 = &direntries[sortvector[i+1]]; assert(d1 != d2); if (d1->sfd_ino == SFS_NOINO) { continue; } if (!strcmp(d1->sfd_name, d2->sfd_name)) { if (d1->sfd_ino == d2->sfd_ino) { setbadness(EXIT_RECOV); warnx("Directory /%s: Duplicate entries for " "%s (merged)", pathsofar, d1->sfd_name); d1->sfd_ino = SFS_NOINO; d1->sfd_name[0] = 0; } else { snprintf(d1->sfd_name, sizeof(d1->sfd_name), "FSCK.%lu.%lu", (unsigned long) d1->sfd_ino, (unsigned long) uniquecounter++); setbadness(EXIT_RECOV); warnx("Directory /%s: Duplicate names %s " "(one renamed: %s)", pathsofar, d2->sfd_name, d1->sfd_name); } dchanged = 1; } } for (i=0; i<ndirentries; i++) { if (!strcmp(direntries[i].sfd_name, ".")) { if (direntries[i].sfd_ino != ino) { setbadness(EXIT_RECOV); warnx("Directory /%s: Incorrect `.' entry " "(fixed)", pathsofar); direntries[i].sfd_ino = ino; dchanged = 1; } assert(dotseen==0); /* due to duplicate checking */ dotseen = 1; } else if (!strcmp(direntries[i].sfd_name, "..")) { if (direntries[i].sfd_ino != parentino) { setbadness(EXIT_RECOV); warnx("Directory /%s: Incorrect `..' entry " "(fixed)", pathsofar); direntries[i].sfd_ino = parentino; dchanged = 1; } assert(dotdotseen==0); /* due to duplicate checking */ dotdotseen = 1; } } if (!dotseen) { if (dir_tryadd(direntries, ndirentries, ".", ino)==0) { setbadness(EXIT_RECOV); warnx("Directory /%s: No `.' entry (added)", pathsofar); dchanged = 1; } else if (dir_tryadd(direntries, maxdirentries, ".", ino)==0) { setbadness(EXIT_RECOV); warnx("Directory /%s: No `.' entry (added)", pathsofar); ndirentries++; dchanged = 1; sfi.sfi_size += sizeof(struct sfs_dir); ichanged = 1; } else { setbadness(EXIT_UNRECOV); warnx("Directory /%s: No `.' entry (NOT FIXED)", pathsofar); } } if (!dotdotseen) { if (dir_tryadd(direntries, ndirentries, "..", parentino)==0) { setbadness(EXIT_RECOV); warnx("Directory /%s: No `..' entry (added)", pathsofar); dchanged = 1; } else if (dir_tryadd(direntries, maxdirentries, "..", parentino)==0) { setbadness(EXIT_RECOV); warnx("Directory /%s: No `..' entry (added)", pathsofar); ndirentries++; dchanged = 1; sfi.sfi_size += sizeof(struct sfs_dir); ichanged = 1; } else { setbadness(EXIT_UNRECOV); warnx("Directory /%s: No `..' entry (NOT FIXED)", pathsofar); } } subdircount=0; for (i=0; i<ndirentries; i++) { if (!strcmp(direntries[i].sfd_name, ".")) { /* nothing */ } else if (!strcmp(direntries[i].sfd_name, "..")) { /* nothing */ } else if (direntries[i].sfd_ino == SFS_NOINO) { /* nothing */ } else { char path[strlen(pathsofar)+SFS_NAMELEN+1]; struct sfs_inode subsfi; diskread(&subsfi, direntries[i].sfd_ino); swapinode(&subsfi); snprintf(path, sizeof(path), "%s/%s", pathsofar, direntries[i].sfd_name); switch (subsfi.sfi_type) { case SFS_TYPE_FILE: if (check_inode_blocks(direntries[i].sfd_ino, &subsfi, 0)) { swapinode(&subsfi); diskwrite(&subsfi, direntries[i].sfd_ino); } observe_filelink(direntries[i].sfd_ino); break; case SFS_TYPE_DIR: if (check_dir(direntries[i].sfd_ino, ino, path)) { setbadness(EXIT_RECOV); warnx("Directory /%s: Crosslink to " "other directory (removed)", path); direntries[i].sfd_ino = SFS_NOINO; direntries[i].sfd_name[0] = 0; dchanged = 1; } else { subdircount++; } break; default: setbadness(EXIT_RECOV); warnx("Object /%s: Invalid inode type " "(removed)", path); direntries[i].sfd_ino = SFS_NOINO; direntries[i].sfd_name[0] = 0; dchanged = 1; break; } } } if (sfi.sfi_linkcount != subdircount+2) { setbadness(EXIT_RECOV); warnx("Directory /%s: Link count %lu should be %lu (fixed)", pathsofar, (unsigned long) sfi.sfi_linkcount, (unsigned long) subdircount+2); sfi.sfi_linkcount = subdircount+2; ichanged = 1; } if (dchanged) { dirwrite(&sfi, direntries, ndirentries); } if (ichanged) { swapinode(&sfi); diskwrite(&sfi, ino); } free(direntries); free(sortvector); return 0; }
/* * Check a directory. INO is the inode number; PATHSOFAR is the path * to this directory. This traverses the volume directory tree * recursively. */ static void pass1_dir(uint32_t ino, const char *pathsofar) { struct sfs_dinode sfi; struct sfs_dir *direntries; uint32_t ndirentries, i; int ichanged=0, dchanged=0; sfs_readinode(ino, &sfi); if (sfi.sfi_size % sizeof(struct sfs_dir) != 0) { setbadness(EXIT_RECOV); warnx("Directory %s has illegal size %lu (fixed)", pathsofar, (unsigned long) sfi.sfi_size); sfi.sfi_size = SFS_ROUNDUP(sfi.sfi_size, sizeof(struct sfs_dir)); ichanged = 1; } count_dirs++; if (pass1_inode(ino, &sfi, ichanged)) { /* been here before; crosslinked dir, sort it out in pass 2 */ return; } ndirentries = sfi.sfi_size/sizeof(struct sfs_dir); direntries = domalloc(sfi.sfi_size); sfs_readdir(&sfi, direntries, ndirentries); for (i=0; i<ndirentries; i++) { if (pass1_direntry(pathsofar, i, &direntries[i])) { dchanged = 1; } } for (i=0; i<ndirentries; i++) { if (direntries[i].sfd_ino == SFS_NOINO) { /* nothing */ } else if (!strcmp(direntries[i].sfd_name, ".")) { /* nothing */ } else if (!strcmp(direntries[i].sfd_name, "..")) { /* nothing */ } else { char path[strlen(pathsofar)+SFS_NAMELEN+1]; struct sfs_dinode subsfi; uint32_t subino; subino = direntries[i].sfd_ino; sfs_readinode(subino, &subsfi); snprintf(path, sizeof(path), "%s/%s", pathsofar, direntries[i].sfd_name); switch (subsfi.sfi_type) { case SFS_TYPE_FILE: if (pass1_inode(subino, &subsfi, 0)) { /* been here before */ break; } count_files++; break; case SFS_TYPE_DIR: pass1_dir(subino, path); break; default: setbadness(EXIT_RECOV); warnx("Object %s: Invalid inode type " "(removed)", path); direntries[i].sfd_ino = SFS_NOINO; direntries[i].sfd_name[0] = 0; dchanged = 1; break; } } } if (dchanged) { sfs_writedir(&sfi, direntries, ndirentries); } free(direntries); }
static void * net_init(int slot, int argc, char *argv[]) { struct net_data *nd = domalloc(sizeof(struct net_data)); const char *hubname = ".sockets/hub"; u_int16_t hwaddr = HUB_ADDR; char cwd[PATH_MAX]; int len; struct sockaddr_un mysun; socklen_t mylen; int i, one=1; for (i=1; i<argc; i++) { if (!strncmp(argv[i], "hub=", 4)) { hubname = argv[i]+4; } else if (!strncmp(argv[i], "hwaddr=", 7)) { hwaddr = atoi(argv[i]+7); } else { msg("nic: slot %d: invalid option %s", slot, argv[i]); die(); } } if (hwaddr == BROADCAST_ADDR || hwaddr == HUB_ADDR) { msg("nic: slot %d: invalid hwaddr or hwaddr not set", slot); die(); } if (getcwd(cwd, sizeof(cwd))==NULL) { msg("nic: slot %d: getcwd: %s", slot, strerror(errno)); die(); } nd->nd_slot = slot; nd->nd_status = ND_STATUS(hwaddr, 0); nd->nd_socket = socket(AF_UNIX, SOCK_DGRAM, 0); if (nd->nd_socket < 0) { msg("nic: slot %d: socket: %s", slot, strerror(errno)); die(); } nd->nd_lostcarrier = 1; nd->nd_rbuf = domalloc(NET_BUFSIZE); nd->nd_wbuf = domalloc(NET_BUFSIZE); memset(&mysun, 0, sizeof(mysun)); mysun.sun_family = AF_UNIX; len = snprintf(mysun.sun_path, sizeof(mysun.sun_path), "%s/.sockets/net-%04x", cwd, hwaddr); if (len < 0 || len >= (int) sizeof(mysun.sun_path)) { msg("nic: slot %d: current directory %s too long", slot, cwd); die(); } mylen = SUN_LEN(&mysun); #ifdef HAS_SUN_LEN mysun.sun_len = mylen; #endif unlink(mysun.sun_path); setsockopt(nd->nd_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)); if (bind(nd->nd_socket, (struct sockaddr *)&mysun, mylen)<0) { msg("nic: slot %d: bind: %s", slot, strerror(errno)); die(); } memset(&nd->nd_hubaddr, 0, sizeof(nd->nd_hubaddr)); nd->nd_hubaddr.sun_family = AF_UNIX; strcpy(nd->nd_hubaddr.sun_path, hubname); nd->nd_hubaddrlen = SUN_LEN(&nd->nd_hubaddr); #ifdef HAS_SUN_LEN nd->nd_hubaddr.sun_len = nd->nd_hubaddrlen; #endif onselect(nd->nd_socket, nd, dorecv, NULL); keepalive(nd, 0); return nd; }