コード例 #1
0
ファイル: Storage.cpp プロジェクト: bq/cervantes
void Storage::checkDevice(int fd) {
    PowerManagerLock* powerLock = PowerManager::getNewLock(this);
    powerLock->activate();
    qDebug() << Q_FUNC_INFO << "FD: "<< fd;

    struct udev_device *dev;
    dev = udev_monitor_receive_device(udev_monitor);
    if (dev)
    {
        QString device = udev_device_get_devnode(dev);
        QString path = udev_device_get_devpath(dev);
        QString action = udev_device_get_action(dev);
        QString devtype = udev_device_get_devtype(dev);
        QString sysname("/dev/");
        sysname += QString(udev_device_get_sysname(dev));
        QString parent = udev_device_get_devpath( udev_device_get_parent (dev));
        if (sysname.contains(QRegExp("mmcblk[0-9]\\d*"))  || sysname.contains(QRegExp("mmcblk[0-9]")))
        {
            qDebug() << "Got " << path << ":" << action;
            qDebug() << "    Got Device";
            qDebug() << "    Node: " <<  udev_device_get_devnode(dev);
            qDebug() << "    Subsystem: "<< udev_device_get_subsystem(dev);
            qDebug() << "    Devtype: " << devtype;
            qDebug() << "    Action: " << action;
            qDebug() << "    Sysname: " << sysname;
            qDebug() << "    sysnum: " << udev_device_get_sysnum (dev);
            qDebug() << "    parent: " << parent;

            processRemovableUdevEvents(devtype, path, sysname, action);
        }
        udev_device_unref(dev);
    }
    delete powerLock;
}
コード例 #2
0
ファイル: mxdial.c プロジェクト: 9fans/plan9port
static void
expand_meta(DS *ds)
{
	static Ndb *db;
	Ndbs s;
	char *sys, *smtpserver;

	/* can't ask cs, so query database directly. */
	sys = sysname();
	if(db == nil)
		db = ndbopen(0);
	smtpserver = ndbgetvalue(db, &s, "sys", sys, "smtp", nil);
	snprint(ds->host, 128, "%s", smtpserver);
}
コード例 #3
0
ファイル: handle_event.c プロジェクト: KapJlcoH/ltrace
static void
handle_syscall(Event *event) {
	debug(DEBUG_FUNCTION, "handle_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
	if (event->proc->state != STATE_IGNORED) {
		callstack_push_syscall(event->proc, event->e_un.sysnum);
		if (options.syscalls) {
			output_left(LT_TOF_SYSCALL, event->proc,
				    sysname(event->proc, event->e_un.sysnum));
		}
		if (event->proc->breakpoints_enabled == 0) {
			enable_all_breakpoints(event->proc);
		}
	}
	continue_after_syscall(event->proc, event->e_un.sysnum, 0);
}
コード例 #4
0
ファイル: Storage.cpp プロジェクト: bq/cervantes
int Storage::enumerate_mmcblk_devices(struct udev *udev)
{
    struct udev_enumerate *udev_enumerate;

    qDebug() << Q_FUNC_INFO << ": enumerate 'block' devices";
    udev_enumerate = udev_enumerate_new(udev);
    if (udev_enumerate == NULL)
        return -1;
    udev_enumerate_add_match_subsystem(udev_enumerate,"block");
    udev_enumerate_scan_devices(udev_enumerate);
    struct udev_list_entry *list_entry;

    udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate))
    {
        struct udev_device *device;

        device = udev_device_new_from_syspath(udev_enumerate_get_udev(udev_enumerate),
                                      udev_list_entry_get_name(list_entry));
        if (device != NULL) {
            QString sysname("/dev/");
            sysname += QString(udev_device_get_sysname(device));
            if (sysname.contains(QRegExp("mmcblk[1-9]\\d*"))  || sysname.contains(QRegExp("mmcblk[1-9]")))
            {
                QString path = udev_device_get_devpath(device);
                QString parent = udev_device_get_devpath( udev_device_get_parent (device));
                QString action = "add";
                QString devtype = udev_device_get_devtype(device);

                qDebug() << "Enumerate device " << path << ":" << action;
                qDebug() << "    Got Device";
                qDebug() << "    Node: " <<  udev_device_get_devnode(device);
                qDebug() << "    Subsystem: "<< udev_device_get_subsystem(device);
                qDebug() << "    Devtype: " << devtype;
                qDebug() << "    Action: " << action;
                qDebug() << "    Sysname: " << sysname;
                qDebug() << "    sysnum: " << udev_device_get_sysnum (device);
                qDebug() << "    parent: " << parent;

                processRemovableUdevEvents(devtype, path, sysname, action);
            }

            udev_device_unref(device);
        }
    }

    udev_enumerate_unref(udev_enumerate);
    return 0;
}
コード例 #5
0
ファイル: handle_event.c プロジェクト: KapJlcoH/ltrace
static void
handle_sysret(Event *event) {
	debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
	if (event->proc->state != STATE_IGNORED) {
		if (opt_T || options.summary) {
			calc_time_spent(event->proc);
		}
		if (options.syscalls) {
			output_right(LT_TOF_SYSCALLR, event->proc,
					sysname(event->proc, event->e_un.sysnum));
		}
		assert(event->proc->callstack_depth > 0);
		unsigned d = event->proc->callstack_depth - 1;
		assert(event->proc->callstack[d].is_syscall);
		callstack_pop(event->proc);
	}
	continue_after_syscall(event->proc, event->e_un.sysnum, 1);
}
コード例 #6
0
ファイル: scp.c プロジェクト: 99years/plan9
void
vprint(char *fmt, ...)
{
	char buf[1024];
	va_list arg;
	static char *name;

	if(vflag == 0)
		return;

	va_start(arg, fmt);
	vseprint(buf, buf+sizeof(buf), fmt, arg);
	va_end(arg);

	if(name == nil){
		name = sysname();
		if(name == nil)
			name = "<unknown>";
	}
	fprint(2, "%s: %s\n", name, buf);
}
コード例 #7
0
ファイル: handle_event.c プロジェクト: KapJlcoH/ltrace
void
handle_event(Event *event) {
	if (exiting == 1) {
		exiting = 2;
		debug(1, "ltrace about to exit");
		ltrace_exiting();
	}
	debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)",
	      event->proc ? event->proc->pid : -1, event->type);

	/* If the thread group or an individual task define an
	   overriding event handler, give them a chance to kick in.
	   We will end up calling both handlers, if the first one
	   doesn't sink the event.  */
	if (event->proc != NULL) {
		event = call_handler(event->proc, event);
		if (event == NULL)
			/* It was handled.  */
			return;

		/* Note: the previous handler has a chance to alter
		 * the event.  */
		if (event->proc != NULL
		    && event->proc->leader != NULL
		    && event->proc != event->proc->leader) {
			event = call_handler(event->proc->leader, event);
			if (event == NULL)
				return;
		}
	}

	switch (event->type) {
	case EVENT_NONE:
		debug(1, "event: none");
		return;
	case EVENT_SIGNAL:
		debug(1, "event: signal (%s [%d])",
		      shortsignal(event->proc, event->e_un.signum),
		      event->e_un.signum);
		handle_signal(event);
		return;
	case EVENT_EXIT:
		debug(1, "event: exit (%d)", event->e_un.ret_val);
		handle_exit(event);
		return;
	case EVENT_EXIT_SIGNAL:
		debug(1, "event: exit signal (%s [%d])",
		      shortsignal(event->proc, event->e_un.signum),
		      event->e_un.signum);
		handle_exit_signal(event);
		return;
	case EVENT_SYSCALL:
		debug(1, "event: syscall (%s [%d])",
		      sysname(event->proc, event->e_un.sysnum),
		      event->e_un.sysnum);
		handle_syscall(event);
		return;
	case EVENT_SYSRET:
		debug(1, "event: sysret (%s [%d])",
		      sysname(event->proc, event->e_un.sysnum),
		      event->e_un.sysnum);
		handle_sysret(event);
		return;
	case EVENT_ARCH_SYSCALL:
		debug(1, "event: arch_syscall (%s [%d])",
				arch_sysname(event->proc, event->e_un.sysnum),
				event->e_un.sysnum);
		handle_arch_syscall(event);
		return;
	case EVENT_ARCH_SYSRET:
		debug(1, "event: arch_sysret (%s [%d])",
				arch_sysname(event->proc, event->e_un.sysnum),
				event->e_un.sysnum);
		handle_arch_sysret(event);
		return;
	case EVENT_CLONE:
	case EVENT_VFORK:
		debug(1, "event: clone (%u)", event->e_un.newpid);
		handle_clone(event);
		return;
	case EVENT_EXEC:
		debug(1, "event: exec()");
		handle_exec(event);
		return;
	case EVENT_BREAKPOINT:
		debug(1, "event: breakpoint");
		handle_breakpoint(event);
		return;
	case EVENT_NEW:
		debug(1, "event: new process");
		handle_new(event);
		return;
	default:
		fprintf(stderr, "Error! unknown event?\n");
		exit(1);
	}
}
コード例 #8
0
ファイル: nsa_result.c プロジェクト: EleanorRobson/oracc
struct nsa_result *
nsa_create_result(struct nsa_parser *p)
{
  struct nsa_token *t;
  struct nsa_result *r = new_result();
  struct nsa_result_chunk *tmp;
  List *rchunks = list_create(LIST_SINGLE);
  int i;
  
  r->success = 1;
  r->ambigs = 0;
  r->parser = p;
  for (t = list_first(p->toks); t; t = list_next(p->toks))
    {
      struct nsa_result_chunk *rc = new_result_chunk();
      List *g;
      struct xl_info *xip;
      int i;
      if (t->type != NSA_T_AMOUNT)
	{
	  /* decompose any partially analyzed elements back into graphemes */
	  g = get_text_refs(t,p->toks,NSA_T_AMOUNT);
	  rc->type = NSA_R_UNPARSED;
	  rc->amount = NULL;
	}
      else
	{
	  g = get_text_refs(t,NULL,NSA_T_NONE);
	  rc->type = NSA_R_PARSED;
	  rc->amount = t->d.a;
	  if (xlink_results)
	    {
	      struct linkset *lsp;
	      const char *override = nsa_system_override_get();
	      if (override)
		{
		  if (amount_measure(t)->type == NSA_T_MEASURE)
		    {
		      t->d.a->measure->d.m->system = new_system();
		      t->d.a->measure->d.m->system->n = override;
		      if (t->d.a->measure->d.m->cands)
			list_free(t->d.a->measure->d.m->cands, NULL);
		    }
		}
	      if (amount_measure(t)->type == NSA_T_MEASURE && t->d.a->measure->d.m->cands)
		{
		  nsa_xcl_warning(p->context->user,
				  t_is_quant(t) ? first_lemm_ptr(t) : first_lemm_ptr_c(t),
				  "ambiguous system: %s", 
				  show_sys_list_str(t->d.a->measure->d.m->cands));
		}
	      else if (amount_measure(t)->type == NSA_T_MEASURE)
		{
		  int ok = 0;
		  if (measure_system(amount_measure(t)) && amount_commodity(t))
		    {
		      List *l;
		      if ((l = hash_find(p->context->comheads,
					 nsa_grapheme_text(t->d.a->commodity->children[0]))))
			{
			  const char *s;
			  ok = -1;
			  for (s = list_first(l); s; s = list_next(l))
			    if (!strcmp(s, sysname(t)))
			      {
				ok = 1;
				break;
			      }
			  if (ok == -1)
			    {
			      if (t->d.a->commodity)
				nsa_xcl_warning(p->context->user,
						t_is_quant(t) ? first_lemm_ptr(t) : first_lemm_ptr_c(t),
						"commodity head `%s' not known for system `%s'",
						nsa_grapheme_text(t->d.a->commodity->children[0]),
						sysname(t));
			    }
			}
		    }
		  if (ok == 0)
		    {
		      const char *pregraph;
		      struct nsa_token **kids;
		      int i;
		      if (amount_measure(t)->type == NSA_T_MEASURE)
			kids = quantity_count(amount_measure(t)->children[0])->children;
		      else
			kids = amount_measure(t)->children;
		      for (i = 0; kids[i]; ++i)
			;
		      pregraph = (const char *)nsa_grapheme_text(kids[i-1]);
		      if (t->d.a->commodity)
			nsa_xcl_warning(p->context->user,
					t_is_quant(t) ? first_lemm_ptr(t) : first_lemm_ptr_c(t),
					"commodity head `%s' unknown; say `%s , %s' if correct",
					nsa_grapheme_text(t->d.a->commodity->children[0]),
					pregraph, nsa_grapheme_text(t->d.a->commodity->children[0])
					);
		    }
		}

	      /* FIXME: we assume for now that measured commodities
		 are not countable; we need to maintain a positive
		 list of countables */
	      else if (amount_measure(t)->type == NSA_T_COUNT 
		       && amount_commodity(t)
		       && commodity_cands(amount_commodity(t)))
		{
		  List *l = hash_find(p->context->comheads,
				      nsa_grapheme_text(t->d.a->commodity->children[0]));
		  int ok = 0;
		  if (l)
		    {
		      const char *s;
		      for (s = list_first(l); s; s = list_next(l))
			if (!strcmp(s, "sexnum"))
			  {
			    ok = 1;
			    break;
			  }
		    }
		  if (!ok)
		    {
		      nsa_xcl_warning(p->context->user,
				      amount_commodity(t)->children[0]->d.g->text->t.lemmptr,
				      "commodity `%s' should be measured not counted",
				      nsa_grapheme_text(t->d.a->commodity->children[0]));
		      commodity_cands(amount_commodity(t)) = NULL;
		    }
		  else if (count_axis(amount_measure(t)) == nsa_sex_asz_axis)
		    nsa_xcl_warning(p->context->user,
				    amount_commodity(t)->children[0]->d.g->text->t.lemmptr,
				    "strange: commodity `%s' is counted in ASZ",
				    nsa_grapheme_text(t->d.a->commodity->children[0]));
		}

	      /* If an NSA_T_AMOUNT without a commodity is followed immediately by another
		 NSA_T_AMOUNT this is an error; the field separator ',' can be used to 
		 suppress this warning */	
	      if (p->toks->rover->next 
		  && ((struct nsa_token *)p->toks->rover->next->data)->type == NSA_T_AMOUNT
		  && !amount_commodity(t))
		{
		  const char *pregraph, *postgraph;
		  struct nsa_token **kids, *ntok = (struct nsa_token *)p->toks->rover->next->data;
		  int i;
		  if (amount_measure(t)->type == NSA_T_MEASURE)
		    {
		      int j;
		      for (j = 0; amount_measure(t)->children[j]; ++j)
			;
		      kids = quantity_count(amount_measure(t)->children[j-1])->children;
		    }
		  else
		    kids = amount_measure(t)->children;
		  for (i = 0; kids[i]; ++i)
		    ;
		  pregraph = (const char *)nsa_grapheme_text(kids[i-1]);
		  if (amount_measure(ntok)->type == NSA_T_MEASURE)
		    kids = quantity_count(amount_measure(ntok)->children[0])->children;
		  else
		    kids = amount_measure(ntok)->children;
		  postgraph = (const char*)nsa_grapheme_text(kids[0]);
		  nsa_xcl_warning(p->context->user,
				  kids[0]->d.g->text->t.lemmptr,
				  "suspicious sequence `%s %s'; lemmatize `n; %% n' if correct",
				  pregraph,postgraph,pregraph,postgraph);
		}
	      if (amount_measure(t)->type == NSA_T_MEASURE)
		{
		  lsp = new_linkset(((struct xcl_context*)p->context->user)->linkbase,
				    "nsa", 
				    (measure_system(amount_measure(t)))
				    ? sysname(t)
				    : ((measure_cands(amount_measure(t)))
					? show_sys_list_str(measure_cands(amount_measure(t)))
				       : "#unknown system#"));
		  lsp->user = nsa_xcl_info(t->d.a);
		  lsp->user_dump_function = (user_dump_func*)nsa_xcl_dump;
		}
	      else
		{
		  lsp = new_linkset(((struct xcl_context*)p->context->user)->linkbase,
				    "nsa", countbase_str(amount_measure(t),p));
		  if (t->type == NSA_T_AMOUNT)
		    {
		      lsp->user = nsa_xcl_info(t->d.a);
		      lsp->user_dump_function = (user_dump_func*)nsa_xcl_dump;
		    }
		  else
		    {
		      lsp->user = NULL;
		    }
		}
	      preallocate_links(lsp,list_len(g));
	      for (i = 0, xip = list_first(g); xip; xip = list_next(g), ++i)
		{
		  struct nsa_text_ref *pg = xip->text;
		  struct link *l = &lsp->links[i];
		  l->lref = pg->t.lemmptr->xml_id;
		  l->lp = pg->t.lemmptr;
		  l->role = xip->role;
		  l->title = (char*)pg->t.lemmptr->f->f2.form;
		  ++lsp->used;
		}

	      /* FUTURE: we can emit commodity links as well with l->role = "c" */

	      /* and we should really emit sysdet links, too */
	    }
	  else if (amount_measure(t)->type == NSA_T_MEASURE && t->d.a->measure->d.m->cands)
	    ++r->ambigs;
	}
コード例 #9
0
ファイル: syslog.c プロジェクト: 8l/NxM
/*
 * Print
 *  sysname: time: mesg
 * on /sys/log/logname.
 * If cons or log file can't be opened, print on the system console, too.
 */
void
syslog(int cons, char *logname, char *fmt, ...)
{
	char buf[1024];
	char *ctim, *p;
	va_list arg;
	int n;
	Dir *d;
	char err[ERRMAX];

	err[0] = '\0';
	errstr(err, sizeof err);
	lock(&sl);

	/*
	 *  paranoia makes us stat to make sure a fork+close
	 *  hasn't broken our fd's
	 */
	d = dirfstat(sl.fd);
	if(sl.fd < 0
	   || sl.name == nil
	   || strcmp(sl.name, logname)!=0
	   || sl.d == nil
	   || d == nil
	   || d->dev != sl.d->dev
	   || d->type != sl.d->type
	   || d->qid.path != sl.d->qid.path){
		free(sl.name);
		sl.name = strdup(logname);
		if(sl.name == nil)
			cons = 1;
		else{
			_syslogopen();
			if(sl.fd < 0)
				cons = 1;
			free(sl.d);
			sl.d = d;
			d = nil;	/* don't free it */
		}
	}
	free(d);
	if(cons){
		d = dirfstat(sl.consfd);
		if(sl.consfd < 0
		   || d == nil
		   || sl.consd == nil
		   || d->dev != sl.consd->dev
		   || d->type != sl.consd->type
		   || d->qid.path != sl.consd->qid.path){
			sl.consfd = open("#c/cons", OWRITE|OCEXEC);
			free(sl.consd);
			sl.consd = d;
			d = nil;	/* don't free it */
		}
		free(d);
	}

	if(fmt == nil){
		unlock(&sl);
		return;
	}

	ctim = ctime(time(0));
	werrstr(err);
	p = buf + snprint(buf, sizeof(buf)-1, "%s ", sysname());
	strncpy(p, ctim+4, 15);
	p += 15;
	*p++ = ' ';
	va_start(arg, fmt);
	p = vseprint(p, buf+sizeof(buf)-1, fmt, arg);
	va_end(arg);
	*p++ = '\n';
	n = p - buf;

	if(sl.fd >= 0){
		seek(sl.fd, 0, 2);
		write(sl.fd, buf, n);
	}

	if(cons && sl.consfd >=0)
		write(sl.consfd, buf, n);

	unlock(&sl);
}
コード例 #10
0
ファイル: plan9.c プロジェクト: HotHat/chibi-scheme
sexp sexp_sysname (sexp ctx, sexp self, sexp_sint_t n) {
  return sexp_c_string(ctx, sysname(), -1);
}
コード例 #11
0
ファイル: vbackup.c プロジェクト: 00001/plan9port
void
threadmain(int argc, char **argv)
{
	char *pref, *mountname, *mountplace;
	uchar score[VtScoreSize], prev[VtScoreSize];
	int i, fd, csize;
	vlong bsize;
	Tm tm;
	VtEntry e;
	VtBlock *b;
	VtCache *c;
	VtRoot root;
	char *tmp, *tmpnam;

	fmtinstall('F', vtfcallfmt);
	fmtinstall('H', encodefmt);
	fmtinstall('T', timefmt);
	fmtinstall('V', vtscorefmt);

	mountname = sysname();
	mountplace = nil;
	ARGBEGIN{
	default:
		usage();
		break;
	case 'D':
		debug++;
		break;
	case 'V':
		chattyventi = 1;
		break;
	case 'f':
		fastwrites = 1;
		break;
	case 'i':
		incremental = 1;
		break;
	case 'm':
		mountname = EARGF(usage());
		break;
	case 'M':
		mountplace = EARGF(usage());
		i = strlen(mountplace);
		if(i > 0 && mountplace[i-1] == '/')
			mountplace[i-1] = 0;
		break;
	case 'n':
		nop = 1;
		break;
	case 's':
		statustime = atoi(EARGF(usage()));
		break;
	case 'v':
		verbose = 1;
		break;
	case 'w':
		nwritethread = atoi(EARGF(usage()));
		break;
	}ARGEND

	if(argc != 1 && argc != 2)
		usage();

	if(statustime)
		print("# %T vbackup %s %s\n", argv[0], argc>=2 ? argv[1] : "");

	/*
	 * open fs
	 */
	if((disk = diskopenfile(argv[0])) == nil)
		sysfatal("diskopen: %r");
	if((disk = diskcache(disk, 32768, 2*MAXQ+16)) == nil)
		sysfatal("diskcache: %r");
	if((fsys = fsysopen(disk)) == nil)
		sysfatal("fsysopen: %r");

	/*
	 * connect to venti
	 */
	if((z = vtdial(nil)) == nil)
		sysfatal("vtdial: %r");
	if(vtconnect(z) < 0)
		sysfatal("vtconnect: %r");

	/*
	 * set up venti block cache
	 */
	zero = vtmallocz(fsys->blocksize);
	bsize = fsys->blocksize;
	csize = 50;	/* plenty; could probably do with 5 */

	if(verbose)
		fprint(2, "cache %d blocks\n", csize);
	c = vtcachealloc(z, bsize*csize);
	zcache = c;

	/*
	 * parse starting score
	 */
	memset(prev, 0, sizeof prev);
	if(argc == 1){
		vfile = vtfilecreateroot(c, (fsys->blocksize/VtScoreSize)*VtScoreSize,
			fsys->blocksize, VtDataType);
		if(vfile == nil)
			sysfatal("vtfilecreateroot: %r");
		vtfilelock(vfile, VtORDWR);
		if(vtfilewrite(vfile, zero, 1, bsize*fsys->nblock-1) != 1)
			sysfatal("vtfilewrite: %r");
		if(vtfileflush(vfile) < 0)
			sysfatal("vtfileflush: %r");
	}else{
		if(vtparsescore(argv[1], &pref, score) < 0)
			sysfatal("bad score: %r");
		if(pref!=nil && strcmp(pref, fsys->type) != 0)
			sysfatal("score is %s but fsys is %s", pref, fsys->type);
		b = vtcacheglobal(c, score, VtRootType, VtRootSize);
		if(b){
			if(vtrootunpack(&root, b->data) < 0)
				sysfatal("bad root: %r");
			if(strcmp(root.type, fsys->type) != 0)
				sysfatal("root is %s but fsys is %s", root.type, fsys->type);
			memmove(prev, score, VtScoreSize);
			memmove(score, root.score, VtScoreSize);
			vtblockput(b);
		}
		b = vtcacheglobal(c, score, VtDirType, VtEntrySize);
		if(b == nil)
			sysfatal("vtcacheglobal %V: %r", score);
		if(vtentryunpack(&e, b->data, 0) < 0)
			sysfatal("%V: vtentryunpack failed", score);
		if(verbose)
			fprint(2, "entry: size %llud psize %d dsize %d\n",
				e.size, e.psize, e.dsize);
		vtblockput(b);
		if((vfile = vtfileopenroot(c, &e)) == nil)
			sysfatal("vtfileopenroot: %r");
		vtfilelock(vfile, VtORDWR);
		if(e.dsize != bsize)
			sysfatal("file system block sizes don't match %d %lld", e.dsize, bsize);
		if(e.size != fsys->nblock*bsize)
			sysfatal("file system block counts don't match %lld %lld", e.size, fsys->nblock*bsize);
	}

	tmpnam = nil;
	if(incremental){
		if(vtfilegetentry(vfile, &e) < 0)
			sysfatal("vtfilegetentry: %r");
		if((vscores = vtfileopenroot(c, &e)) == nil)
			sysfatal("vtfileopenroot: %r");
		vtfileunlock(vfile);
	}else{
		/*
		 * write scores of blocks into temporary file
		 */
		if((tmp = getenv("TMP")) != nil){
			/* okay, good */
		}else if(access("/var/tmp", 0) >= 0)
			tmp = "/var/tmp";
		else
			tmp = "/tmp";
		tmpnam = smprint("%s/vbackup.XXXXXX", tmp);
		if(tmpnam == nil)
			sysfatal("smprint: %r");
	
		if((fd = opentemp(tmpnam, ORDWR|ORCLOSE)) < 0)
			sysfatal("opentemp %s: %r", tmpnam);
		if(statustime)
			print("# %T reading scores into %s\n", tmpnam);
		if(verbose)
			fprint(2, "read scores into %s...\n", tmpnam);
	
		Binit(&bscores, fd, OWRITE);
		for(i=0; i<fsys->nblock; i++){
			if(vtfileblockscore(vfile, i, score) < 0)
				sysfatal("vtfileblockhash %d: %r", i);
			if(Bwrite(&bscores, score, VtScoreSize) != VtScoreSize)
				sysfatal("Bwrite: %r");
		}
		Bterm(&bscores);
		vtfileunlock(vfile);
	
		/*
		 * prep scores for rereading
		 */
		seek(fd, 0, 0);
		Binit(&bscores, fd, OREAD);
	}

	/*
	 * start the main processes 
	 */
	if(statustime)
		print("# %T starting procs\n");
	qcmp = qalloc();
	qventi = qalloc();

	rlock(&endlk);
	proccreate(fsysproc, nil, STACK);
	rlock(&endlk);
	proccreate(ventiproc, nil, STACK);
	rlock(&endlk);
	proccreate(cmpproc, nil, STACK);
	if(statustime){
		rlock(&endlk);
		proccreate(statusproc, nil, STACK);
	}

	/*
	 * wait for processes to finish
	 */
	wlock(&endlk);
	
	qfree(qcmp);
	qfree(qventi);

	if(statustime)
		print("# %T procs exited: %d of %d %d-byte blocks changed, "
			"%d read, %d written, %d skipped, %d copied\n",
			nchange, fsys->nblock, fsys->blocksize,
			vtcachenread, vtcachenwrite, nskip, vtcachencopy);

	/*
	 * prepare root block
	 */
	if(incremental)
		vtfileclose(vscores);
	vtfilelock(vfile, -1);
	if(vtfileflush(vfile) < 0)
		sysfatal("vtfileflush: %r");
	if(vtfilegetentry(vfile, &e) < 0)
		sysfatal("vtfilegetentry: %r");
	vtfileunlock(vfile);
	vtfileclose(vfile);

	b = vtcacheallocblock(c, VtDirType, VtEntrySize);
	if(b == nil)
		sysfatal("vtcacheallocblock: %r");
	vtentrypack(&e, b->data, 0);
	if(vtblockwrite(b) < 0)
		sysfatal("vtblockwrite: %r");

	memset(&root, 0, sizeof root);
	strecpy(root.name, root.name+sizeof root.name, argv[0]);
	strecpy(root.type, root.type+sizeof root.type, fsys->type);
	memmove(root.score, b->score, VtScoreSize);
	root.blocksize = fsys->blocksize;
	memmove(root.prev, prev, VtScoreSize);
	vtblockput(b);

	b = vtcacheallocblock(c, VtRootType, VtRootSize);
	if(b == nil)
		sysfatal("vtcacheallocblock: %r");
	vtrootpack(&root, b->data);
	if(vtblockwrite(b) < 0)
		sysfatal("vtblockwrite: %r");

	tm = *localtime(time(0));
	tm.year += 1900;
	tm.mon++;
	if(mountplace == nil)
		mountplace = guessmountplace(argv[0]);
	print("mount /%s/%d/%02d%02d%s %s:%V %d/%02d%02d/%02d%02d\n",
		mountname, tm.year, tm.mon, tm.mday, 
		mountplace,
		root.type, b->score,
		tm.year, tm.mon, tm.mday, tm.hour, tm.min);
	print("# %T %s %s:%V\n", argv[0], root.type, b->score);
	if(statustime)
		print("# %T venti sync\n");
	vtblockput(b);
	if(vtsync(z) < 0)
		sysfatal("vtsync: %r");
	if(statustime)
		print("# %T synced\n");
	
	fsysclose(fsys);
	diskclose(disk);
	vtcachefree(zcache);

	// Vtgoodbye hangs on Linux - not sure why.
	// Probably vtfcallrpc doesn't quite get the
	// remote hangup right.  Also probably related
	// to the vtrecvproc problem below.
	// vtgoodbye(z);

	// Leak here, because I can't seem to make
	// the vtrecvproc exit.
	// vtfreeconn(z);

	free(tmpnam);
	z = nil;
	zcache = nil;
	fsys = nil;
	disk = nil;
	threadexitsall(nil);
}