예제 #1
0
static int
sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp)
{
	Qid q;
	uvlong l;
	int i, r;
	SDpart *pp;
	SDunit *unit;
	SDev *sdev;

	switch(TYPE(c->qid)){
	case Qtopdir:
		if(s == DEVDOTDOT){
			mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);
			snprint(up->genbuf, sizeof up->genbuf, "#%C",
				sddevtab.dc);
			devdir(c, q, up->genbuf, 0, eve, 0555, dp);
			return 1;
		}

		if(s+Qtopbase < Qunitdir)
			return sd1gen(c, s+Qtopbase, dp);
		s -= (Qunitdir-Qtopbase);

		qlock(&devslock);
		for(i=0; i<nelem(devs); i++){
			if(devs[i]){
				if(s < devs[i]->nunit)
					break;
				s -= devs[i]->nunit;
			}
		}

		if(i == nelem(devs)){
			/* Run off the end of the list */
			qunlock(&devslock);
			return -1;
		}

		if((sdev = devs[i]) == nil){
			qunlock(&devslock);
			return 0;
		}

		incref(&sdev->r);
		qunlock(&devslock);

		if((unit = sdev->unit[s]) == nil)
			if((unit = sdgetunit(sdev, s)) == nil){
				decref(&sdev->r);
				return 0;
			}

		mkqid(&q, QID(sdev->idno, s, 0, Qunitdir), 0, QTDIR);
		if(emptystr(unit->user))
			kstrdup(&unit->user, eve);
		devdir(c, q, unit->name, 0, unit->user, unit->perm, dp);
		decref(&sdev->r);
		return 1;

	case Qunitdir:
		if(s == DEVDOTDOT){
			mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);
			snprint(up->genbuf, sizeof up->genbuf, "#%C",
				sddevtab.dc);
			devdir(c, q, up->genbuf, 0, eve, 0555, dp);
			return 1;
		}

		if((sdev = sdgetdev(DEV(c->qid))) == nil){
			devdir(c, c->qid, "unavailable", 0, eve, 0, dp);
			return 1;
		}

		unit = sdev->unit[UNIT(c->qid)];
		qlock(&unit->ctl);

		/*
		 * Check for media change.
		 * If one has already been detected, sectors will be zero.
		 * If there is one waiting to be detected, online
		 * will return > 1.
		 * Online is a bit of a large hammer but does the job.
		 */
		if(unit->sectors == 0
		|| (unit->dev->ifc->online && unit->dev->ifc->online(unit) > 1))
			sdinitpart(unit);

		i = s+Qunitbase;
		if(i < Qpart){
			r = sd2gen(c, i, dp);
			qunlock(&unit->ctl);
			decref(&sdev->r);
			return r;
		}
		i -= Qpart;
		if(unit->part == nil || i >= unit->npart){
			qunlock(&unit->ctl);
			decref(&sdev->r);
			break;
		}
		pp = &unit->part[i];
		if(!pp->valid){
			qunlock(&unit->ctl);
			decref(&sdev->r);
			return 0;
		}
		l = (pp->end - pp->start) * unit->secsize;
		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart),
			unit->vers+pp->vers, QTFILE);
		if(emptystr(pp->user))
			kstrdup(&pp->user, eve);
		devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
		qunlock(&unit->ctl);
		decref(&sdev->r);
		return 1;
	case Qraw:
	case Qctl:
	case Qpart:
		if((sdev = sdgetdev(DEV(c->qid))) == nil){
			devdir(c, q, "unavailable", 0, eve, 0, dp);
			return 1;
		}
		unit = sdev->unit[UNIT(c->qid)];
		qlock(&unit->ctl);
		r = sd2gen(c, TYPE(c->qid), dp);
		qunlock(&unit->ctl);
		decref(&sdev->r);
		return r;
	case Qtopctl:
		return sd1gen(c, TYPE(c->qid), dp);
	default:
		break;
	}

	return -1;
}
예제 #2
0
파일: gsc.c 프로젝트: npe9/spin
int gscread  (dev_t dev, struct uio *uio, int ioflag)
{
    int unit = UNIT(minor(dev));
    struct gsc_unit *scu = unittab + unit;
    size_t nbytes;
    int res;

    lprintf("gsc%d.read: minor %d\n", unit, minor(dev));

    if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
    {
        lprintf("gsc%d.read: unit was not attached successfully 0x04x\n",
                unit, scu->flags);
        return ENXIO;
    }

    if ( !(scu->flags & READING) )
    {
        res = buffer_allocate(scu);
        if ( res == SUCCESS )
            scu->flags |= READING;
        else
            return res;

        scu->ctrl_byte = geomtab[scu->geometry].s_res;

        /* initialize for pbm mode */
        if ( scu->flags & PBM_MODE )
        {
            char *p;
            int width = geomtab[scu->geometry].dpl;

            sprintf(scu->sbuf.base,"P4 %d %d\n", width, scu->height);
            scu->bcount = scu->height * width / 8;

            lprintf("gsc%d.read: initializing pbm mode: `%s', bcount: 0x%x\n",
                    unit, scu->sbuf.base, scu->bcount);

            /* move header to end of sbuf */
            for(p=scu->sbuf.base; *p; p++);
            while(--p >= scu->sbuf.base)
            {
                *(char *)(scu->sbuf.base + --scu->sbuf.poi) = *p;
                scu->bcount++;
            }
        }
    }

    lprintf("gsc%d.read(before buffer_read): "
            "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
            unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount);

    if ( scu->sbuf.poi == scu->sbuf.size )
        if ( (res = buffer_read(scu)) != SUCCESS )
            return res;

    lprintf("gsc%d.read(after buffer_read): "
            "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
            unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount);

    nbytes = MIN( uio->uio_resid, scu->sbuf.size - scu->sbuf.poi );

    if ( (scu->flags & PBM_MODE) )
        nbytes = MIN( nbytes, scu->bcount );

    lprintf("gsc%d.read: transferring 0x%x bytes", nbytes);

    res = uiomove(scu->sbuf.base + scu->sbuf.poi, nbytes, uio);
    if ( res != SUCCESS )
    {
        lprintf("gsc%d.read: uiomove failed %d", unit, res);
        return res;
    }

    scu->sbuf.poi += nbytes;
    if ( scu->flags & PBM_MODE ) scu->bcount -= nbytes;

    lprintf("gsc%d.read: size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
            unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount);

    return SUCCESS;
}
예제 #3
0
파일: automount.c 프로젝트: teg/systemd
static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        union autofs_v5_packet_union packet;
        Automount *a = AUTOMOUNT(userdata);
        Unit *trigger;
        int r;

        assert(a);
        assert(fd == a->pipe_fd);

        if (events != EPOLLIN) {
                log_unit_error(UNIT(a), "Got invalid poll event %"PRIu32" on pipe (fd=%d)", events, fd);
                goto fail;
        }

        r = loop_read_exact(a->pipe_fd, &packet, sizeof(packet), true);
        if (r < 0) {
                log_unit_error_errno(UNIT(a), r, "Invalid read from pipe: %m");
                goto fail;
        }

        switch (packet.hdr.type) {

        case autofs_ptype_missing_direct:

                if (packet.v5_packet.pid > 0) {
                        _cleanup_free_ char *p = NULL;

                        get_process_comm(packet.v5_packet.pid, &p);
                        log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p));
                } else
                        log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where);

                r = set_ensure_allocated(&a->tokens, NULL);
                if (r < 0) {
                        log_unit_error(UNIT(a), "Failed to allocate token set.");
                        goto fail;
                }

                r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                if (r < 0) {
                        log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
                        goto fail;
                }

                automount_enter_running(a);
                break;

        case autofs_ptype_expire_direct:
                log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where);

                automount_stop_expire(a);

                r = set_ensure_allocated(&a->expire_tokens, NULL);
                if (r < 0) {
                        log_unit_error(UNIT(a), "Failed to allocate token set.");
                        goto fail;
                }

                r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                if (r < 0) {
                        log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
                        goto fail;
                }

                trigger = UNIT_TRIGGER(UNIT(a));
                if (!trigger) {
                        log_unit_error(UNIT(a), "Unit to trigger vanished.");
                        goto fail;
                }

                r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, &error, NULL);
                if (r < 0) {
                        log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
                        goto fail;
                }
                break;

        default:
                log_unit_error(UNIT(a), "Received unknown automount request %i", packet.hdr.type);
                break;
        }

        return 0;

fail:
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
        return 0;
}
예제 #4
0
파일: devaoe.c 프로젝트: CoryXie/nix-os
static int
aoegen(Chan *c, char *, Dirtab *, int, int s, Dir *dp)
{
	int i;
	Aoedev *d;
	Qid q;

	if(c->qid.path == 0){
		switch(s){
		case DEVDOTDOT:
			q.path = 0;
			q.type = QTDIR;
			devdir(c, q, "#æ", 0, eve, 0555, dp);
			break;
		case 0:
			q.path = Qtopdir;
			q.type = QTDIR;
			devdir(c, q, "aoe", 0, eve, 0555, dp);
			break;
		default:
			return -1;
		}
		return 1;
	}

	switch(TYPE(c->qid)){
	default:
		return -1;
	case Qtopdir:
		if(s == DEVDOTDOT){
			mkqid(&q, Qzero, 0, QTDIR);
			devdir(c, q, "aoe", 0, eve, 0555, dp);
			return 1;
		}
		if(s < Qtopfiles)
			return topgen(c, Qtopbase + s, dp);
		s -= Qtopfiles;
		if(s >= units.ref)
			return -1;
		mkqid(&q, QID(s, Qunitdir), 0, QTDIR);
		d = unit2dev(s);
		devdir(c, q, unitname(d), 0, eve, 0555, dp);
		return 1;
	case Qtopctl:
	case Qtoplog:
		return topgen(c, TYPE(c->qid), dp);
	case Qunitdir:
		if(s == DEVDOTDOT){
			mkqid(&q, QID(0, Qtopdir), 0, QTDIR);
			uprint("%uld", UNIT(c->qid));
			devdir(c, q, up->genbuf, 0, eve, 0555, dp);
			return 1;
		}
		return unitgen(c, Qunitbase+s, dp);
	case Qctl:
	case Qdata:
	case Qconfig:
	case Qident:
		return unitgen(c, TYPE(c->qid), dp);
	case Qdevlinkdir:
		i = UNIT(c->qid);
		if(s == DEVDOTDOT){
			mkqid(&q, QID(i, Qunitdir), 0, QTDIR);
			devdir(c, q, "devlink", 0, eve, 0555, dp);
			return 1;
		}
		if(i >= units.ref)
			return -1;
		d = unit2dev(i);
		if(s >= d->ndl)
			return -1;
		uprint("%d", s);
		mkqid(&q, Q3(s, i, Qdevlink), 0, QTFILE);
		devdir(c, q, up->genbuf, 0, eve, 0755, dp);
		return 1;
	case Qdevlink:
		uprint("%d", s);
		mkqid(&q, Q3(s, UNIT(c->qid), Qdevlink), 0, QTFILE);
		devdir(c, q, up->genbuf, 0, eve, 0755, dp);
		return 1;
	}
}
예제 #5
0
int
parrw(dev_t dev, register struct uio *uio)
{
  int unit = UNIT(dev);
  register struct par_softc *sc = getparsp(unit);
  register int s, len, cnt;
  register char *cp;
  int error = 0, gotdata = 0;
  int buflen;
  char *buf;

  len = 0;
  cnt = 0;
  if (!!(sc->sc_flags & PARF_OREAD) ^ (uio->uio_rw == UIO_READ))
    return EINVAL;

  if (uio->uio_resid == 0)
    return(0);

#ifdef DEBUG
  if (pardebug & (PDB_FOLLOW|PDB_IO))
    printf("parrw(%llx, %p, %c): burst %d, timo %d, resid %x\n",
	   dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W',
	   sc->sc_burst, sc->sc_timo, uio->uio_resid);
#endif
  buflen = min(sc->sc_burst, uio->uio_resid);
  buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK);
  sc->sc_flags |= PARF_UIO;
  if (sc->sc_timo > 0)
    {
      sc->sc_flags |= PARF_TIMO;
      callout_reset(&sc->sc_timo_ch, sc->sc_timo, partimo, sc);
    }
  while (uio->uio_resid > 0)
    {
      len = min(buflen, uio->uio_resid);
      cp = buf;
      if (uio->uio_rw == UIO_WRITE)
	{
	  error = uiomove(cp, len, uio);
	  if (error)
	    break;
	}
again:
#if 0
      if ((sc->sc_flags & PARF_UIO) && hpibreq(&sc->sc_dq) == 0)
	sleep(sc, PRIBIO+1);
#endif
      /*
       * Check if we timed out during sleep or uiomove
       */
      s = splsoftclock();
      if ((sc->sc_flags & PARF_UIO) == 0)
	{
#ifdef DEBUG
	  if (pardebug & PDB_IO)
	    printf("parrw: uiomove/sleep timo, flags %x\n",
		   sc->sc_flags);
#endif
	  if (sc->sc_flags & PARF_TIMO)
	    {
	      callout_stop(&sc->sc_timo_ch);
	      sc->sc_flags &= ~PARF_TIMO;
	    }
	  splx(s);
	  break;
	}
      splx(s);
      /*
       * Perform the operation
       */
      if (uio->uio_rw == UIO_WRITE)
	cnt = parsend (cp, len);
      else
	cnt = parreceive (cp, len);

      if (cnt < 0)
	{
	  error = -cnt;
	  break;
	}

      s = splbio();
#if 0
      hpibfree(&sc->sc_dq);
#endif
#ifdef DEBUG
      if (pardebug & PDB_IO)
	printf("parrw: %s(%p, %d) -> %d\n",
	       uio->uio_rw == UIO_READ ? "recv" : "send", cp, len, cnt);
#endif
      splx(s);
      if (uio->uio_rw == UIO_READ)
	{
	  if (cnt)
	    {
	      error = uiomove(cp, cnt, uio);
	      if (error)
		break;
	      gotdata++;
	    }
	  /*
	   * Didn't get anything this time, but did in the past.
	   * Consider us done.
	   */
	  else if (gotdata)
	    break;
	}
      s = splsoftclock();
      /*
       * Operation timeout (or non-blocking), quit now.
       */
      if ((sc->sc_flags & PARF_UIO) == 0)
	{
#ifdef DEBUG
	  if (pardebug & PDB_IO)
	    printf("parrw: timeout/done\n");
#endif
	  splx(s);
	  break;
	}
      /*
       * Implement inter-read delay
       */
      if (sc->sc_delay > 0)
	{
	  sc->sc_flags |= PARF_DELAY;
	  callout_reset(&sc->sc_start_ch, sc->sc_delay, parstart, sc);
	  error = tsleep(sc, PCATCH | (PZERO - 1), "par-cdelay", 0);
	  if (error)
	    {
	      splx(s);
	      break;
	    }
	}
      splx(s);
      /*
       * Must not call uiomove again til we've used all data
       * that we already grabbed.
       */
      if (uio->uio_rw == UIO_WRITE && cnt != len)
	{
	  cp += cnt;
	  len -= cnt;
	  cnt = 0;
	  goto again;
	}
    }
  s = splsoftclock();
  if (sc->sc_flags & PARF_TIMO)
    {
      callout_stop(&sc->sc_timo_ch);
      sc->sc_flags &= ~PARF_TIMO;
    }
  if (sc->sc_flags & PARF_DELAY)
    {
      callout_stop(&sc->sc_start_ch);
      sc->sc_flags &= ~PARF_DELAY;
    }
  splx(s);
  /*
   * Adjust for those chars that we uiomove'ed but never wrote
   */
  if (uio->uio_rw == UIO_WRITE && cnt != len)
    {
      uio->uio_resid += (len - cnt);
#ifdef DEBUG
      if (pardebug & PDB_IO)
	printf("parrw: short write, adjust by %d\n",
	       len-cnt);
#endif
    }
  free(buf, M_DEVBUF);
#ifdef DEBUG
  if (pardebug & (PDB_FOLLOW|PDB_IO))
    printf("parrw: return %d, resid %d\n", error, uio->uio_resid);
#endif
  return (error);
}
예제 #6
0
파일: test.c 프로젝트: ZyX-I/stderred
  // Reset again and use a regex for our name
  stderred.reset();
  setenv("STDERRED_BLACKLIST", "test_.*", 1);
  stderred.init();

  // Verify the blacklist accepts the regex and marks env as invalid
  assert(!*stderred.has_valid_env);

  // Test to make sure above did not pass because of false positives
  stderred.reset();
  stderred.init();
  assert(*stderred.has_valid_env);
}

unit_test tests[] = {
  UNIT(printf),
  UNIT(write),
  UNIT(fwrite),
  UNIT(fwrite_unlocked),
  UNIT(fputc),
  UNIT(fputc_unlocked),
  UNIT(fputs),
  UNIT(fputs_unlocked),
  UNIT(fprintf),
  UNIT(fprintf_unlocked),
  UNIT(vfprintf),
  UNIT(perror),
  UNIT(error),
  UNIT(error_at_line),
  UNIT(err),
  UNIT(verr),
예제 #7
0
파일: busname.c 프로젝트: achanda/systemd
static int busname_peek_message(BusName *n) {
        struct kdbus_cmd_recv cmd_recv = {
                .size = sizeof(cmd_recv),
                .flags = KDBUS_RECV_PEEK,
        };
        struct kdbus_cmd_free cmd_free = {
                .size = sizeof(cmd_free),
        };
        const char *comm = NULL;
        struct kdbus_item *d;
        struct kdbus_msg *k;
        size_t start, ps, sz, delta;
        void *p = NULL;
        pid_t pid = 0;
        int r;

        /* Generate a friendly debug log message about which process
         * caused triggering of this bus name. This simply peeks the
         * metadata of the first queued message and logs it. */

        assert(n);

        /* Let's shortcut things a bit, if debug logging is turned off
         * anyway. */

        if (log_get_max_level() < LOG_DEBUG)
                return 0;

        r = ioctl(n->starter_fd, KDBUS_CMD_RECV, &cmd_recv);
        if (r < 0) {
                if (errno == EINTR || errno == EAGAIN)
                        return 0;

                return log_unit_error_errno(UNIT(n), errno, "Failed to query activation message: %m");
        }

        /* We map as late as possible, and unmap imemdiately after
         * use. On 32bit address space is scarce and we want to be
         * able to handle a lot of activator connections at the same
         * time, and hence shouldn't keep the mmap()s around for
         * longer than necessary. */

        ps = page_size();
        start = (cmd_recv.msg.offset / ps) * ps;
        delta = cmd_recv.msg.offset - start;
        sz = PAGE_ALIGN(delta + cmd_recv.msg.msg_size);

        p = mmap(NULL, sz, PROT_READ, MAP_SHARED, n->starter_fd, start);
        if (p == MAP_FAILED) {
                r = log_unit_error_errno(UNIT(n), errno, "Failed to map activation message: %m");
                goto finish;
        }

        k = (struct kdbus_msg *) ((uint8_t *) p + delta);
        KDBUS_ITEM_FOREACH(d, k, items) {
                switch (d->type) {

                case KDBUS_ITEM_PIDS:
                        pid = d->pids.pid;
                        break;

                case KDBUS_ITEM_PID_COMM:
                        comm = d->str;
                        break;
                }
        }

        if (pid > 0)
                log_unit_debug(UNIT(n), "Activation triggered by process " PID_FMT " (%s)", pid, strna(comm));

        r = 0;

finish:
        if (p)
                (void) munmap(p, sz);

        cmd_free.offset = cmd_recv.msg.offset;
        if (ioctl(n->starter_fd, KDBUS_CMD_FREE, &cmd_free) < 0)
                log_unit_warning(UNIT(n), "Failed to free peeked message, ignoring: %m");

        return r;
}

static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
        BusName *n = userdata;

        assert(n);
        assert(fd >= 0);

        if (n->state != BUSNAME_LISTENING)
                return 0;

        log_unit_debug(UNIT(n), "Activation request");

        if (revents != EPOLLIN) {
                log_unit_error(UNIT(n), "Got unexpected poll event (0x%x) on starter fd.", revents);
                goto fail;
        }

        busname_peek_message(n);
        busname_enter_running(n);
        return 0;
fail:

        busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
        return 0;
}

static void busname_sigchld_event(Unit *u, pid_t pid, int code, int status) {
        BusName *n = BUSNAME(u);
        BusNameResult f;

        assert(n);
        assert(pid >= 0);

        if (pid != n->control_pid)
                return;

        n->control_pid = 0;

        if (is_clean_exit(code, status, NULL))
                f = BUSNAME_SUCCESS;
        else if (code == CLD_EXITED)
                f = BUSNAME_FAILURE_EXIT_CODE;
        else if (code == CLD_KILLED)
                f = BUSNAME_FAILURE_SIGNAL;
        else if (code == CLD_DUMPED)
                f = BUSNAME_FAILURE_CORE_DUMP;
        else
                assert_not_reached("Unknown sigchld code");

        log_unit_full(u, f == BUSNAME_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0,
                      "Control process exited, code=%s status=%i", sigchld_code_to_string(code), status);

        if (n->result == BUSNAME_SUCCESS)
                n->result = f;

        switch (n->state) {

        case BUSNAME_MAKING:
                if (f == BUSNAME_SUCCESS)
                        busname_enter_listening(n);
                else
                        busname_enter_signal(n, BUSNAME_SIGTERM, f);
                break;

        case BUSNAME_SIGTERM:
        case BUSNAME_SIGKILL:
                busname_enter_dead(n, f);
                break;

        default:
                assert_not_reached("Uh, control process died at wrong time.");
        }

        /* Notify clients about changed exit status */
        unit_add_to_dbus_queue(u);
}
예제 #8
0
파일: devsd.c 프로젝트: srk-cmu/9problems
static int
sdwstat(Chan* c, uchar* dp, int n)
{
	Dir *d;
	SDpart *pp;
	SDperm *perm;
	SDunit *unit;
	SDev *sdev;

	if(c->qid.type & QTDIR)
		error(Eperm);
	if(TYPE(c->qid) == Qtopctl){
		unit = &topctlunit;
		sdev = nil;
	}else{
		sdev = sdgetdev(DEV(c->qid));
		if(sdev == nil)
			error(Enonexist);
		unit = sdev->unit[UNIT(c->qid)];
	}
	qlock(&unit->ctl);

	d = nil;
	if(waserror()){
		qunlock(&unit->ctl);
		if(sdev != nil)
			decref(&sdev->r);
		free(d);
		nexterror();
	}

	switch(TYPE(c->qid)){
	default:
		error(Eperm);
	case Qtopctl:
	case Qctl:
		perm = &unit->ctlperm;
		break;
	case Qraw:
		perm = &unit->rawperm;
		break;
	case Qpart:
		pp = &unit->part[PART(c->qid)];
		if(unit->vers+pp->vers != c->qid.vers)
			error(Enonexist);
		perm = &pp->SDperm;
		break;
	}

	if(strcmp(up->user, perm->user) && !iseve())
		error(Eperm);

	d = smalloc(sizeof(Dir)+n);
	n = convM2D(dp, n, &d[0], (char*)&d[1]);
	if(n == 0)
		error(Eshortstat);
	if(d->atime != ~0 ||  d->mtime  != ~0 ||  d->length  != ~0)
		error(Eperm);
	if(!emptystr(d[0].muid) || !emptystr(d[0].name))
		error(Eperm);
	if(!emptystr(d[0].uid))
		kstrdup(&perm->user, d[0].uid);
	if(!emptystr(d[0].gid) && strcmp(d[0].gid, eve) != 0)
		error(Eperm);
	if(d[0].mode != ~0UL)
		perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777);
	poperror();
	qunlock(&unit->ctl);
	if(sdev != nil)
		decref(&sdev->r);
	free(d);
	return n;
}
예제 #9
0
파일: devsd.c 프로젝트: srk-cmu/9problems
static int
sd2gen(Chan* c, int i, Dir* dp)
{
	Qid q;
	uvlong l;
	SDfile *e;
	SDpart *pp;
	SDperm *perm;
	SDunit *unit;
	SDev *sdev;
	int rv, t;

	sdev = sdgetdev(DEV(c->qid));
	assert(sdev);
	unit = sdev->unit[UNIT(c->qid)];

	rv = -1;
	switch(i){
	case Qctl:
		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl),
			unit->vers, QTFILE);
		perm = &unit->ctlperm;
		if(emptystr(perm->user)){
			kstrdup(&perm->user, eve);
			perm->perm = 0640;
		}
		devdir(c, q, "ctl", 0, perm->user, perm->perm, dp);
		rv = 1;
		break;

	case Qraw:
		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw),
			unit->vers, QTFILE);
		perm = &unit->rawperm;
		if(emptystr(perm->user)){
			kstrdup(&perm->user, eve);
			perm->perm = DMEXCL|0600;
		}
		devdir(c, q, "raw", 0, perm->user, perm->perm, dp);
		rv = 1;
		break;

	case Qpart:
		pp = &unit->part[PART(c->qid)];
		l = (pp->end - pp->start) * unit->secsize;
		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qpart),
			unit->vers+pp->vers, QTFILE);
		if(emptystr(pp->user))
			kstrdup(&pp->user, eve);
		devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
		rv = 1;
		break;
	case Qextra:
		t = PART(c->qid);
		if(t >= unit->nefile)
			break;
		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qextra),
			unit->vers, QTFILE);
		e = unit->efile + t;
		if(emptystr(e->user))
			kstrdup(&e->user, eve);
		devdir(c, q, e->name, 0, e->user, e->perm, dp);
		rv = 1;
		break;
	}

	decref(&sdev->r);
	return rv;
}
예제 #10
0
파일: automount.c 프로젝트: swem/systemd
static void automount_enter_waiting(Automount *a) {
        _cleanup_close_ int ioctl_fd = -1;
        int p[2] = { -1, -1 };
        char name[sizeof("systemd-")-1 + DECIMAL_STR_MAX(pid_t) + 1];
        char options[sizeof("fd=,pgrp=,minproto=5,maxproto=5,direct")-1
                     + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1];
        bool mounted = false;
        int r, dev_autofs_fd;
        struct stat st;

        assert(a);
        assert(a->pipe_fd < 0);
        assert(a->where);

        set_clear(a->tokens);

        r = unit_fail_if_symlink(UNIT(a), a->where);
        if (r < 0)
                goto fail;

        (void) mkdir_p_label(a->where, 0555);

        unit_warn_if_dir_nonempty(UNIT(a), a->where);

        dev_autofs_fd = open_dev_autofs(UNIT(a)->manager);
        if (dev_autofs_fd < 0) {
                r = dev_autofs_fd;
                goto fail;
        }

        if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
                r = -errno;
                goto fail;
        }

        xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp());
        xsprintf(name, "systemd-"PID_FMT, getpid());
        if (mount(name, a->where, "autofs", 0, options) < 0) {
                r = -errno;
                goto fail;
        }

        mounted = true;

        p[1] = safe_close(p[1]);

        if (stat(a->where, &st) < 0) {
                r = -errno;
                goto fail;
        }

        ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev);
        if (ioctl_fd < 0) {
                r = ioctl_fd;
                goto fail;
        }

        r = autofs_protocol(dev_autofs_fd, ioctl_fd);
        if (r < 0)
                goto fail;

        r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, a->timeout_idle_usec);
        if (r < 0)
                goto fail;

        /* Autofs fun fact:
         *
         * Unless we close the ioctl fd here, for some weird reason
         * the direct mount will not receive events from the
         * kernel. */

        r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a);
        if (r < 0)
                goto fail;

        (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");

        a->pipe_fd = p[0];
        a->dev_id = st.st_dev;

        automount_set_state(a, AUTOMOUNT_WAITING);

        return;

fail:
        safe_close_pair(p);

        if (mounted)
                repeat_unmount(a->where);

        log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m");
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
}
예제 #11
0
파일: automount.c 프로젝트: swem/systemd
static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        union autofs_v5_packet_union packet;
        Automount *a = AUTOMOUNT(userdata);
        struct stat st;
        int r;

        assert(a);
        assert(fd == a->pipe_fd);

        if (events != EPOLLIN) {
                log_unit_error(UNIT(a), "Got invalid poll event %"PRIu32" on pipe (fd=%d)", events, fd);
                goto fail;
        }

        r = loop_read_exact(a->pipe_fd, &packet, sizeof(packet), true);
        if (r < 0) {
                log_unit_error_errno(UNIT(a), r, "Invalid read from pipe: %m");
                goto fail;
        }

        switch (packet.hdr.type) {

        case autofs_ptype_missing_direct:

                if (packet.v5_packet.pid > 0) {
                        _cleanup_free_ char *p = NULL;

                        get_process_comm(packet.v5_packet.pid, &p);
                        log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p));
                } else
                        log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where);

                r = set_ensure_allocated(&a->tokens, NULL);
                if (r < 0) {
                        log_unit_error(UNIT(a), "Failed to allocate token set.");
                        goto fail;
                }

                r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                if (r < 0) {
                        log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
                        goto fail;
                }

                automount_enter_runnning(a);
                break;

        case autofs_ptype_expire_direct:
                log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where);

                (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF);

                r = set_ensure_allocated(&a->expire_tokens, NULL);
                if (r < 0) {
                        log_unit_error(UNIT(a), "Failed to allocate token set.");
                        goto fail;
                }

                r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                if (r < 0) {
                        log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
                        goto fail;
                }

                /* Before we do anything, let's see if somebody is playing games with us? */
                if (lstat(a->where, &st) < 0) {
                        log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m");
                        goto fail;
                }

                if (!S_ISDIR(st.st_mode) || st.st_dev == a->dev_id) {
                        log_unit_info(UNIT(a), "Automount point already unmounted?");
                        automount_send_ready(a, a->expire_tokens, 0);
                        break;
                }

                r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, true, &error, NULL);
                if (r < 0) {
                        log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
                        goto fail;
                }
                break;

        default:
                log_unit_error(UNIT(a), "Received unknown automount request %i", packet.hdr.type);
                break;
        }

        return 0;

fail:
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
        return 0;
}
예제 #12
0
파일: fwiso.c 프로젝트: MarginC/kame
int
fwisoioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
{
	int unit = UNIT(dev);
	struct fwiso_data *fd;
	int error = 0;

	if (unit >= NFWISO) {
		return ENXIO;
	}

	fd = &fwiso_data_str[unit];

	if (!data) {
		return EINVAL;
	}

	switch(cmd) {

	case FWISOSETIF:
	    {
		const struct fwiso_if *fi = (struct fwiso_if *)data;

		if ((fd->fd_dev = fwiso_lookup_if(fi->fi_name)) == NULL) {
			error = EINVAL;
		}
		break;
	    }
	case FWISOGETIF:
	    {
		struct fwiso_if *fi = (struct fwiso_if *)data;

		if (fd->fd_dev != NULL) {
			memcpy(fi->fi_name, fd->fd_dev->sc1394_dev.dv_xname,
			    FWISO_IFNAMESIZ);
		} else {
			memcpy(fi->fi_name, "---", 3);
		}
		break;
	    }
	case FWISOSETMODE:
	    {
		const int mode = *(int *)data;

		if (mode >= 0 && mode < FWISO_MODE_MAX) {
			fd->fd_mode = mode;
		} else {
			error = EINVAL;
		}
		break;
	    }
	case FWISOGETMODE:
		*((int *)data) = fd->fd_mode;
		break;
	case FWISOSETCHANNEL:
	    {
		const int channel = *(int *)data;

		if (channel >= 0 && channel < 64) {
			fd->fd_channel = channel;
		} else if (channel == FWISO_CHANNEL_ANY) {
			fd->fd_channel = IEEE1394_ISO_CHANNEL_ANY;
		} else {
			error = EINVAL;
		}
		break;
	    }
	case FWISOGETCHANNEL:
		*((int *)data) = fd->fd_channel;
		break;
	case FWISOSETTAG:
	    {
		const int tag = *(int *)data;

#define FWISO_TAG_MAX (FWISO_TAG0 | FWISO_TAG1 | FWISO_TAG2 | FWISO_TAG3)

		if (tag >= FWISO_TAG0 || tag <= FWISO_TAG_MAX) {
			/* valid tag */
			fd->fd_tag = tag;
		} else {
			error = EINVAL;
		}
	    }
	case FWISOGETTAG:
		*((int *)data) = fd->fd_tag;
		break;
	default:
		error = EINVAL;
		break;
	}
	
	return error;
}
예제 #13
0
파일: fwiso.c 프로젝트: MarginC/kame
/*
 * int fwisowrite(dev_t dev, struct uio *uio, int ioflag)
 *
 *	Write routine
 */
int
fwisowrite(dev_t dev, struct uio *uio, int ioflag)
{
	struct fwiso_data *fd;
	int unit;
	int rv = ENODEV;

	unit = UNIT(dev);

	if (unit >= NFWISO) {
		return ENXIO;
	}

	if (IOCTL(dev)) {
		DPRINTF(("fwiso%d cannot read\n", unit));
		return ENXIO;
	}

	fd = &fwiso_data_str[unit];

	if ((fd->fd_flags & FWISO_OPEN) == 0) {
		return EBUSY;
	}

	if (fd->fd_ittag == NULL) {
		/* XXX */
		if (fd->fd_channel < 0) {
			fd->fd_channel = 63;
		}
		if (fd->fd_tag <= 0) {
			fd->fd_tag = IEEE1394_ISO_TAG1;
		}
		fd->fd_ittag = fwohci_it_set(fd->fd_dev, fd->fd_channel,
		    fd->fd_tag);
		if (fd->fd_ittag == NULL) {
			return EBUSY;
		}
		fd->fd_flags |= FWISO_WRITE;
		printf("fwiso%d: it_set returns %p\n", unit, fd->fd_ittag);

		fd->fd_it_dv_insert_fractional = 16000;
		fd->fd_it_dv_insert_fraction = 1015;
		fd->fd_it_dv_insert_empty = 0;

#define ITLISTSIZE sizeof(struct ieee1394_it_datalist)*100
		if ((fd->fd_itlist = malloc(ITLISTSIZE, M_DEVBUF,
		    M_WAITOK|M_ZERO)) == NULL) {
			/*  */
			printf("fwiso%d: cannot get memory for it_list\n",
			    unit);
			return EBUSY;
		}

		/* XXX */
		fd->fd_cycletimer = fwohci_it_cycletimer(fd->fd_ittag);
		printf("cycletimer %x %d %d\n", fd->fd_cycletimer,
		    fd->fd_cycletimer >> 13, fd->fd_cycletimer&0x1fff);
	}
#if 1
	switch(fd->fd_mode) {
	case FWISO_MODE_DV:
		rv = fwisowrite_dv(fd, uio, 480);
		break;
	case FWISO_MODE_DV_RAW:
		break;
	case FWISO_MODE_RAW:
		break;
	}

#endif

	return rv;
}
예제 #14
0
파일: fwiso.c 프로젝트: MarginC/kame
/*
 * int fwisoread(dev_t dev, struct uio *uio, int ioflag)
 *
 *     Read routine
 *
 *     Algorithm:
 *
 *       if interrupt handler is not set
 *           register interrupt handler
 *           prepare reserve buffer;
 *       if some data exists in reserve buffer
 *           copy data in uio
 *           if uio is full
 *               return
 *       set uio in interrupt handler
 *       sleep until interrupt handler wait me
 *       set reserve buffer
 *       return
 */
int
fwisoread(dev_t dev, struct uio *uio, int ioflag)
{
	struct fwiso_data *fd;
	int unit;
	int status = 0;
	int s;

	int minspace;
	int headoffs;
	volatile struct fwiso_pktdata *pkt;
	struct fwiso_pktdata *pkt_last;
	struct ieee1394_softc *isc;
	size_t resid;

	int i;

	unit = UNIT(dev);

	if (unit >= NFWISO) {
		return ENXIO;
	}

	if (IOCTL(dev)) {
		DPRINTF(("fwiso%d cannot read\n", unit));
		return ENXIO;
	}

	fd = &fwiso_data_str[unit];

	if ((fd->fd_flags & FWISO_OPEN) == 0) {
		return EBUSY;
	}

	isc = fd->fd_dev;

	if ((fd->fd_flags & FWISO_SETHANDLER) == 0) {
		int rv;

		if ((rv = fwiso_set_handler(fd)) != 0) {
			return rv;
		}
	}

	minspace = fwiso_min_space[fd->fd_mode];
	headoffs = fwiso_head_offset[fd->fd_mode];

	/* This is constant */
	pkt_last = fd->fd_rsv_pkts.fp_iov_last;
	/* Only fwiso writes.  Others read only */
	pkt = fd->fd_rsv_pkts.fp_iov_start;

	s = splbio();

	i = 0;
	resid = uio->uio_resid;
	DPRINTF(("%s: now reading\n", isc->sc1394_dev.dv_xname));
	while ((status = (*isc->sc1394_ir_read)((struct device *)isc,
	    fd->fd_irtag, uio, headoffs, 0)) == EAGAIN
	    || (status == 0 && uio->uio_resid == resid)) {
		if (fd->fd_flags & FWISO_NONBLOCK) {
			break;
		}
		if (isc->sc1394_ir_wait == NULL) {
			if (++i > 20) {
				status = EIO;
				break;
			}
			delay(100);
		} else {
			status = (*isc->sc1394_ir_wait)((struct device *)isc,
			    fd->fd_irtag, (void *)fd, fd->fd_devname);
			if (status != 0) {
				break;
			}
		}
	}

	splx(s);

	return status;
}
예제 #15
0
static long
sdbio(Chan* c, int write, char* a, long len, uvlong off)
{
	int nchange;
	long l;
	uchar *b;
	SDpart *pp;
	SDunit *unit;
	SDev *sdev;
	ulong max, nb, offset;
	uvlong bno;

	sdev = sdgetdev(DEV(c->qid));
	if(sdev == nil){
		decref(&sdev->r);
		error(Enonexist);
	}
	unit = sdev->unit[UNIT(c->qid)];
	if(unit == nil)
		error(Enonexist);

	nchange = 0;
	qlock(&unit->ctl);
	while(waserror()){
		/* notification of media change; go around again */
		if(strcmp(up->env->errstr, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){
			sdinitpart(unit);
			continue;
		}

		/* other errors; give up */
		qunlock(&unit->ctl);
		decref(&sdev->r);
		nexterror();
	}
	pp = &unit->part[PART(c->qid)];
	if(unit->vers+pp->vers != c->qid.vers)
		error(Echange);

	/*
	 * Check the request is within bounds.
	 * Removeable drives are locked throughout the I/O
	 * in case the media changes unexpectedly.
	 * Non-removeable drives are not locked during the I/O
	 * to allow the hardware to optimise if it can; this is
	 * a little fast and loose.
	 * It's assumed that non-removeable media parameters
	 * (sectors, secsize) can't change once the drive has
	 * been brought online.
	 */
	bno = (off/unit->secsize) + pp->start;
	nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
	max = SDmaxio/unit->secsize;
	if(nb > max)
		nb = max;
	if(bno+nb > pp->end)
		nb = pp->end - bno;
	if(bno >= pp->end || nb == 0){
		if(write)
			error(Eio);
		qunlock(&unit->ctl);
		decref(&sdev->r);
		poperror();
		return 0;
	}
	if(!(unit->inquiry[1] & SDinq1removable)){
		qunlock(&unit->ctl);
		poperror();
	}

	b = sdmalloc(nb*unit->secsize);
	if(b == nil)
		error(Enomem);
	if(waserror()){
		sdfree(b);
		if(!(unit->inquiry[1] & SDinq1removable))
			decref(&sdev->r);		/* gadverdamme! */
		nexterror();
	}

	offset = off%unit->secsize;
	if(offset+len > nb*unit->secsize)
		len = nb*unit->secsize - offset;
	if(write){
		if(offset || (len%unit->secsize)){
			l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
			if(l < 0)
				error(Eio);
			if(l < (nb*unit->secsize)){
				nb = l/unit->secsize;
				l = nb*unit->secsize - offset;
				if(len > l)
					len = l;
			}
		}
		memmove(b+offset, a, len);
		l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno);
		if(l < 0)
			error(Eio);
		if(l < offset)
			len = 0;
		else if(len > l - offset)
			len = l - offset;
	}
	else{
		l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
		if(l < 0)
			error(Eio);
		if(l < offset)
			len = 0;
		else if(len > l - offset)
			len = l - offset;
		memmove(a, b+offset, len);
	}
	sdfree(b);
	poperror();

	if(unit->inquiry[1] & SDinq1removable){
		qunlock(&unit->ctl);
		poperror();
	}

	decref(&sdev->r);
	return len;
}
예제 #16
0
static int bus_scope_set_transient_property(
                Scope *s,
                const char *name,
                sd_bus_message *message,
                UnitWriteFlags flags,
                sd_bus_error *error) {

        int r;

        assert(s);
        assert(name);
        assert(message);

        flags |= UNIT_PRIVATE;

        if (streq(name, "TimeoutStopUSec"))
                return bus_set_transient_usec(UNIT(s), name, &s->timeout_stop_usec, message, flags, error);

        if (streq(name, "PIDs")) {
                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                unsigned n = 0;

                r = sd_bus_message_enter_container(message, 'a', "u");
                if (r < 0)
                        return r;

                for (;;) {
                        uint32_t upid;
                        pid_t pid;

                        r = sd_bus_message_read(message, "u", &upid);
                        if (r < 0)
                                return r;
                        if (r == 0)
                                break;

                        if (upid == 0) {
                                if (!creds) {
                                        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                                        if (r < 0)
                                                return r;
                                }

                                r = sd_bus_creds_get_pid(creds, &pid);
                                if (r < 0)
                                        return r;
                        } else
                                pid = (uid_t) upid;

                        r = unit_pid_attachable(UNIT(s), pid, error);
                        if (r < 0)
                                return r;

                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                r = unit_watch_pid(UNIT(s), pid);
                                if (r < 0 && r != -EEXIST)
                                        return r;
                        }

                        n++;
                }

                r = sd_bus_message_exit_container(message);
                if (r < 0)
                        return r;

                if (n <= 0)
                        return -EINVAL;

                return 1;

        } else if (streq(name, "Controller")) {
                const char *controller;

                /* We can't support direct connections with this, as direct connections know no service or unique name
                 * concept, but the Controller field stores exactly that. */
                if (sd_bus_message_get_bus(message) != UNIT(s)->manager->api_bus)
                        return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Sorry, Controller= logic only supported via the bus.");

                r = sd_bus_message_read(message, "s", &controller);
                if (r < 0)
                        return r;

                if (!isempty(controller) && !service_name_is_valid(controller))
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);

                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                        r = free_and_strdup(&s->controller, empty_to_null(controller));
                        if (r < 0)
                                return r;
                }

                return 1;
        }

        return 0;
}
예제 #17
0
파일: mt.c 프로젝트: lacombar/netbsd-alc
static int
mtopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct mt_softc *sc;
	int req_den;
	int error;

	sc = device_lookup_private(&mt_cd, UNIT(dev));
	if (sc == NULL)
		return ENXIO;

	if ((sc->sc_flags & MTF_EXISTS) == 0)
		return ENXIO;

	dlog(LOG_DEBUG, "%s open: flags 0x%x", device_xname(sc->sc_dev),
	    sc->sc_flags);
	if (sc->sc_flags & MTF_OPEN)
		return EBUSY;
	sc->sc_flags |= MTF_OPEN;
	sc->sc_ttyp = tprintf_open(l->l_proc);
	if ((sc->sc_flags & MTF_ALIVE) == 0) {
		error = mtcommand(dev, MTRESET, 0);
		if (error != 0 || (sc->sc_flags & MTF_ALIVE) == 0)
			goto errout;
		if ((sc->sc_stat1 & (SR1_BOT | SR1_ONLINE)) == SR1_ONLINE)
			(void) mtcommand(dev, MTREW, 0);
	}
	for (;;) {
		if ((error = mtcommand(dev, MTNOP, 0)) != 0)
			goto errout;
		if (!(sc->sc_flags & MTF_REW))
			break;
		if (tsleep((void *) &lbolt, PCATCH | (PZERO + 1),
		    "mt", 0) != 0) {
			error = EINTR;
			goto errout;
		}
	}
	if ((flag & FWRITE) && (sc->sc_stat1 & SR1_RO)) {
		error = EROFS;
		goto errout;
	}
	if (!(sc->sc_stat1 & SR1_ONLINE)) {
		uprintf("%s: not online\n", device_xname(sc->sc_dev));
		error = EIO;
		goto errout;
	}
	/*
	 * Select density:
	 *  - find out what density the drive is set to
	 *	(i.e. the density of the current tape)
	 *  - if we are going to write
	 *    - if we're not at the beginning of the tape
	 *      - complain if we want to change densities
	 *    - otherwise, select the mtcommand to set the density
	 *
	 * If the drive doesn't support it then don't change the recorded
	 * density.
	 *
	 * The original MOREbsd code had these additional conditions
	 * for the mid-tape change
	 *
	 *	req_den != T_BADBPI &&
	 *	sc->sc_density != T_6250BPI
	 *
	 * which suggests that it would be possible to write multiple
	 * densities if req_den == T_BAD_BPI or the current tape
	 * density was 6250.  Testing of our 7980 suggests that the
	 * device cannot change densities mid-tape.
	 *
	 * [email protected]
	 */
	sc->sc_density = (sc->sc_stat2 & SR2_6250) ? T_6250BPI : (
			 (sc->sc_stat3 & SR3_1600) ? T_1600BPI : (
			 (sc->sc_stat3 & SR3_800) ? T_800BPI : -1));
	req_den = (dev & T_DENSEL);

	if (flag & FWRITE) {
		if (!(sc->sc_stat1 & SR1_BOT)) {
			if (sc->sc_density != req_den) {
				uprintf("%s: can't change density mid-tape\n",
				    device_xname(sc->sc_dev));
				error = EIO;
				goto errout;
			}
		}
		else {
			int mtset_density =
			    (req_den == T_800BPI  ? MTSET800BPI : (
			     req_den == T_1600BPI ? MTSET1600BPI : (
			     req_den == T_6250BPI ? MTSET6250BPI : (
			     sc->sc_type == MT7980ID
						  ? MTSET6250DC
						  : MTSET6250BPI))));
			if (mtcommand(dev, mtset_density, 0) == 0)
				sc->sc_density = req_den;
		}
	}
	return 0;
errout:
	sc->sc_flags &= ~MTF_OPEN;
	return error;
}
예제 #18
0
static int bus_scope_abandon(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
        Scope *s = userdata;
        int r;

        assert(bus);
        assert(message);
        assert(s);

        r = scope_abandon(s);
        if (sd_bus_error_is_set(error))
                return r;

        if (r == -ESTALE)
                return sd_bus_error_setf(error, BUS_ERROR_SCOPE_NOT_RUNNING, "Scope %s is not running, cannot abandon.", UNIT(s)->id);

        return sd_bus_reply_method_return(message, NULL);
}
예제 #19
0
파일: automount.c 프로젝트: ariscop/systemd
static void automount_enter_waiting(Automount *a) {
        int p[2] = { -1, -1 };
        char name[32], options[128];
        bool mounted = false;
        int r, ioctl_fd = -1, dev_autofs_fd;
        struct stat st;

        assert(a);
        assert(a->pipe_fd < 0);
        assert(a->where);

        if (a->tokens)
                set_clear(a->tokens);

        dev_autofs_fd = open_dev_autofs(UNIT(a)->manager);
        if (dev_autofs_fd < 0) {
                r = dev_autofs_fd;
                goto fail;
        }

        /* We knowingly ignore the results of this call */
        mkdir_p_label(a->where, 0555);

        warn_if_dir_nonempty(a->meta.id, a->where);

        if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
                r = -errno;
                goto fail;
        }

        snprintf(options, sizeof(options), "fd=%i,pgrp=%u,minproto=5,maxproto=5,direct", p[1], (unsigned) getpgrp());
        char_array_0(options);

        snprintf(name, sizeof(name), "systemd-%u", (unsigned) getpid());
        char_array_0(name);

        if (mount(name, a->where, "autofs", 0, options) < 0) {
                r = -errno;
                goto fail;
        }

        mounted = true;

        close_nointr_nofail(p[1]);
        p[1] = -1;

        if (stat(a->where, &st) < 0) {
                r = -errno;
                goto fail;
        }

        ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev);
        if (ioctl_fd < 0) {
                r = ioctl_fd;
                goto fail;
        }

        r = autofs_protocol(dev_autofs_fd, ioctl_fd);
        if (r < 0)
                goto fail;

        r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, 300);
        if (r < 0)
                goto fail;

        /* Autofs fun fact:
         *
         * Unless we close the ioctl fd here, for some weird reason
         * the direct mount will not receive events from the
         * kernel. */

        close_nointr_nofail(ioctl_fd);
        ioctl_fd = -1;

        r = sd_event_add_io(UNIT(a)->manager->event, p[0], EPOLLIN, automount_dispatch_io, a, &a->pipe_event_source);
        if (r < 0)
                goto fail;

        a->pipe_fd = p[0];
        a->dev_id = st.st_dev;

        automount_set_state(a, AUTOMOUNT_WAITING);

        return;

fail:
        assert_se(close_pipe(p) == 0);

        if (ioctl_fd >= 0)
                close_nointr_nofail(ioctl_fd);

        if (mounted)
                repeat_unmount(a->where);

        log_error_unit(UNIT(a)->id,
                       "Failed to initialize automounter: %s", strerror(-r));
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
}
예제 #20
0
static int bus_scope_set_transient_property(
                Scope *s,
                const char *name,
                sd_bus_message *message,
                UnitSetPropertiesMode mode,
                sd_bus_error *error) {

        int r;

        assert(s);
        assert(name);
        assert(message);

        if (streq(name, "PIDs")) {
                unsigned n = 0;
                uint32_t pid;

                r = sd_bus_message_enter_container(message, 'a', "u");
                if (r < 0)
                        return r;

                while ((r = sd_bus_message_read(message, "u", &pid)) > 0) {

                        if (pid <= 1)
                                return -EINVAL;

                        if (mode != UNIT_CHECK) {
                                r = unit_watch_pid(UNIT(s), pid);
                                if (r < 0 && r != -EEXIST)
                                        return r;
                        }

                        n++;
                }
                if (r < 0)
                        return r;

                r = sd_bus_message_exit_container(message);
                if (r < 0)
                        return r;

                if (n <= 0)
                        return -EINVAL;

                return 1;

        } else if (streq(name, "Controller")) {
                const char *controller;
                char *c;

                r = sd_bus_message_read(message, "s", &controller);
                if (r < 0)
                        return r;

                if (!isempty(controller) && !service_name_is_valid(controller))
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);

                if (mode != UNIT_CHECK) {
                        if (isempty(controller))
                                c = NULL;
                        else {
                                c = strdup(controller);
                                if (!c)
                                        return -ENOMEM;
                        }

                        free(s->controller);
                        s->controller = c;
                }

                return 1;

        } else if (streq(name, "TimeoutStopUSec")) {

                if (mode != UNIT_CHECK) {
                        r = sd_bus_message_read(message, "t", &s->timeout_stop_usec);
                        if (r < 0)
                                return r;

                        unit_write_drop_in_format(UNIT(s), mode, name, "[Scope]\nTimeoutStopSec=%lluus\n", (unsigned long long) s->timeout_stop_usec);
                } else {
                        r = sd_bus_message_skip(message, "t");
                        if (r < 0)
                                return r;
                }

                return 1;
        }

        return 0;
}
예제 #21
0
static int bus_scope_set_transient_property(
                Scope *s,
                const char *name,
                sd_bus_message *message,
                UnitSetPropertiesMode mode,
                sd_bus_error *error) {

        int r;

        assert(s);
        assert(name);
        assert(message);

        if (streq(name, "PIDs")) {
                unsigned n = 0;
                uint32_t pid;

                r = set_ensure_allocated(&s->pids, trivial_hash_func, trivial_compare_func);
                if (r < 0)
                        return r;

                r = sd_bus_message_enter_container(message, 'a', "u");
                if (r < 0)
                        return r;

                while ((r = sd_bus_message_read(message, "u", &pid)) > 0) {

                        if (pid <= 1)
                                return -EINVAL;

                        if (mode != UNIT_CHECK) {
                                r = set_put(s->pids, LONG_TO_PTR(pid));
                                if (r < 0 && r != -EEXIST)
                                        return r;
                        }

                        n++;
                }
                if (r < 0)
                        return r;

                r = sd_bus_message_exit_container(message);
                if (r < 0)
                        return r;

                if (n <= 0)
                        return -EINVAL;

                return 1;

        } else if (streq(name, "TimeoutStopUSec")) {

                if (mode != UNIT_CHECK) {
                        r = sd_bus_message_read(message, "t", &s->timeout_stop_usec);
                        if (r < 0)
                                return r;

                        unit_write_drop_in_format(UNIT(s), mode, name, "[Scope]\nTimeoutStopSec=%lluus\n", (unsigned long long) s->timeout_stop_usec);
                } else {
                        r = sd_bus_message_skip(message, "t");
                        if (r < 0)
                                return r;
                }

                return 1;
        }

        return 0;
}
예제 #22
0
파일: par.c 프로젝트: lacombar/netbsd-alc
int
parrw(dev_t dev, struct uio *uio)
{
	int unit = UNIT(dev);
	struct par_softc *sc = device_lookup_private(&par_cd, unit);
	int len=0xdeadbeef;	/* XXX: shutup gcc */
	int s, cnt=0;
	char *cp;
	int error = 0;
	int buflen;
	char *buf;
	
	if (!!(sc->sc_flags & PARF_OREAD) ^ (uio->uio_rw == UIO_READ))
		return EINVAL;
	
	if (uio->uio_resid == 0)
		return(0);
	
	buflen = min(sc->sc_burst, uio->uio_resid);
	buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK);
	sc->sc_flags |= PARF_UIO;
	if (sc->sc_timo > 0) {
		sc->sc_flags |= PARF_TIMO;
		callout_reset(&sc->sc_timo_ch, sc->sc_timo, partimo, sc);
	}
	while (uio->uio_resid > 0) {
		len = min(buflen, uio->uio_resid);
		cp = buf;
		if (uio->uio_rw == UIO_WRITE) {
			error = uiomove(cp, len, uio);
			if (error)
				break;
		}
	      again:
		s = splsoftclock();
		/*
		 * Check if we timed out during sleep or uiomove
		 */
		if ((sc->sc_flags & PARF_UIO) == 0) {
#ifdef DEBUG
			if (pardebug & PDB_IO)
				printf("parrw: uiomove/sleep timo, flags %x\n",
				       sc->sc_flags);
#endif
			if (sc->sc_flags & PARF_TIMO) {
				callout_stop(&sc->sc_timo_ch);
				sc->sc_flags &= ~PARF_TIMO;
			}
			splx(s);
			break;
		}
		splx(s);
		/*
		 * Perform the operation
		 */
		cnt = parsend(sc, cp, len);
		if (cnt < 0) {
			error = -cnt;
			break;
		}
		
		s = splsoftclock();
		/*
		 * Operation timeout (or non-blocking), quit now.
		 */
		if ((sc->sc_flags & PARF_UIO) == 0) {
#ifdef DEBUG
			if (pardebug & PDB_IO)
				printf("parrw: timeout/done\n");
#endif
			splx(s);
			break;
		}
		/*
		 * Implement inter-read delay
		 */
		if (sc->sc_delay > 0) {
			sc->sc_flags |= PARF_DELAY;
			callout_reset(&sc->sc_start_ch, sc->sc_delay,
			    parstart, sc);
			error = tsleep(sc, PCATCH|(PZERO-1), "par-cdelay", 0);
			if (error) {
				splx(s);
				break;
			}
		}
		splx(s);
		/*
		 * Must not call uiomove again til we've used all data
		 * that we already grabbed.
		 */
		if (uio->uio_rw == UIO_WRITE && cnt != len) {
			cp += cnt;
			len -= cnt;
			cnt = 0;
			goto again;
		}
	}
	s = splsoftclock();
	if (sc->sc_flags & PARF_TIMO) {
		callout_stop(&sc->sc_timo_ch);
		sc->sc_flags &= ~PARF_TIMO;
	}
	if (sc->sc_flags & PARF_DELAY)	{
		callout_stop(&sc->sc_start_ch);
		sc->sc_flags &= ~PARF_DELAY;
	}
	splx(s);
	/*
	 * Adjust for those chars that we uiomove'ed but never wrote
	 */
	/*
	 * XXXjdolecek: this len usage is wrong, this will be incorrect
	 * if the transfer size is longer than sc_burst
	 */
	if (uio->uio_rw == UIO_WRITE && cnt != len) {
		uio->uio_resid += (len - cnt);
#ifdef DEBUG
			if (pardebug & PDB_IO)
				printf("parrw: short write, adjust by %d\n",
				       len-cnt);
#endif
	}
	free(buf, M_DEVBUF);
#ifdef DEBUG
	if (pardebug & (PDB_FOLLOW|PDB_IO))
		printf("parrw: return %d, resid %d\n", error, uio->uio_resid);
#endif
	return (error);
}
예제 #23
0
파일: wst.c 프로젝트: UnitedMarsupials/kame
int 
wstioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
{
    int lun = UNIT(dev);
    int error = 0;
    struct wst *t = wsttab[lun];

    switch (cmd) {
    case MTIOCGET:
	{
            struct mtget *g = (struct mtget *) addr;

            bzero(g, sizeof(struct mtget));
            g->mt_type = 7;
            g->mt_density = 1;
            g->mt_blksiz = t->blksize;
            g->mt_comp = t->cap.compress;
            g->mt_density0 = 0; g->mt_density1 = 0;
            g->mt_density2 = 0; g->mt_density3 = 0;
            g->mt_blksiz0 = 0; g->mt_blksiz1 = 0;
            g->mt_blksiz2 = 0; g->mt_blksiz3 = 0;
            g->mt_comp0 = 0; g->mt_comp1 = 0;
            g->mt_comp2 = 0; g->mt_comp3 = 0;
            break;       
	}
    case MTIOCTOP:
        {       
	    int i;
    	    struct mtop *mt = (struct mtop *)addr;

            switch ((short) (mt->mt_op)) {
            case MTWEOF:
		for (i=0; i < mt->mt_count && !error; i++)
			error = wst_write_filemark(t, WEOF_WRITE_MASK);
                break;
            case MTFSF:
		if (mt->mt_count)
			error = wst_space_cmd(t, SP_FM, mt->mt_count);
                break;
            case MTBSF:
		if (mt->mt_count)
			error = wst_space_cmd(t, SP_FM, -(mt->mt_count));
                break;
            case MTFSR:
                error = EINVAL; break;
            case MTBSR:
                error = EINVAL; break;
            case MTREW:
                error = wst_rewind(t);
		break;
            case MTOFFL:
#if 1				/* Misuse as a reset func for now */
		wst_reset(t);
		wst_sense(t);
		wst_describe(t);
#else
                if (error = wst_rewind(t))
		    break;
                error = wst_load_unload(t, !LU_LOAD_MASK);
#endif
		    break;
            case MTNOP:
		error = wst_write_filemark(t, 0);
                break;
            case MTCACHE:
                error = EINVAL; break;
            case MTNOCACHE:
                error = EINVAL; break;
            case MTSETBSIZ:
                error = EINVAL; break;
            case MTSETDNSTY:
                error = EINVAL; break;
            case MTERASE:
                error = wst_erase(t);
		break;
            case MTEOD:
		error = wst_space_cmd(t, SP_EOD, 0);
                break;
            case MTCOMP:
                error = EINVAL; break;
            case MTRETENS:
                error = wst_load_unload(t, LU_RETENSION_MASK|LU_LOAD_MASK);
		break;
            default:
                error = EINVAL;
            }
            return error;
        }
    default:
        return(ENOTTY);
    }
    return(error);
}
예제 #24
0
static long
sdread(Chan *c, void *a, long n, vlong off)
{
	char *p, *e, *buf;
	SDpart *pp;
	SDunit *unit;
	SDev *sdev;
	ulong offset;
	int i, l, m, status;

	offset = off;
	switch(TYPE(c->qid)){
	default:
		error(Eperm);
	case Qtopctl:
		m = 64*1024;	/* room for register dumps */
		p = buf = malloc(m);
		if(p == nil)
			error(Enomem);
		e = p + m;
		qlock(&devslock);
		for(i = 0; i < nelem(devs); i++){
			sdev = devs[i];
			if(sdev && sdev->ifc->rtopctl)
				p = sdev->ifc->rtopctl(sdev, p, e);
		}
		qunlock(&devslock);
		n = readstr(off, a, n, buf);
		free(buf);
		return n;

	case Qtopdir:
	case Qunitdir:
		return devdirread(c, a, n, 0, 0, sdgen);

	case Qctl:
		sdev = sdgetdev(DEV(c->qid));
		if(sdev == nil)
			error(Enonexist);

		unit = sdev->unit[UNIT(c->qid)];
		m = 16*1024;	/* room for register dumps */
		p = malloc(m);
		if(p == nil)
			error(Enomem);
		l = snprint(p, m, "inquiry %.48s\n",
			(char*)unit->inquiry+8);
		qlock(&unit->ctl);
		/*
		 * If there's a device specific routine it must
		 * provide all information pertaining to night geometry
		 * and the garscadden trains.
		 */
		if(unit->dev->ifc->rctl)
			l += unit->dev->ifc->rctl(unit, p+l, m-l);
		if(unit->sectors == 0)
			sdinitpart(unit);
		if(unit->sectors){
			if(unit->dev->ifc->rctl == nil)
				l += snprint(p+l, m-l,
					"geometry %llud %lud\n",
					unit->sectors, unit->secsize);
			pp = unit->part;
			for(i = 0; i < unit->npart; i++){
				if(pp->valid)
					l += snprint(p+l, m-l,
						"part %s %llud %llud\n",
						pp->name, pp->start, pp->end);
				pp++;
			}
		}
		qunlock(&unit->ctl);
		decref(&sdev->r);
		l = readstr(offset, a, n, p);
		free(p);
		return l;

	case Qraw:
		sdev = sdgetdev(DEV(c->qid));
		if(sdev == nil)
			error(Enonexist);

		unit = sdev->unit[UNIT(c->qid)];
		qlock(&unit->raw);
		if(waserror()){
			qunlock(&unit->raw);
			decref(&sdev->r);
			nexterror();
		}
		if(unit->state == Rawdata){
			unit->state = Rawstatus;
			i = sdrio(unit->req, a, n);
		}
		else if(unit->state == Rawstatus){
			status = unit->req->status;
			unit->state = Rawcmd;
			free(unit->req);
			unit->req = nil;
			i = readnum(0, a, n, status, NUMSIZE);
		} else
			i = 0;
		qunlock(&unit->raw);
		decref(&sdev->r);
		poperror();
		return i;

	case Qpart:
		return sdbio(c, 0, a, n, off);
	}
}
예제 #25
0
int main(int argc, char*argv[]) {
        JobType a, b, c, ab, bc, ab_c, bc_a, a_bc;
        const ServiceState test_states[] = { SERVICE_DEAD, SERVICE_RUNNING };
        unsigned i;
        bool merged_ab;

        /* fake a unit */
        static Service s = {
                .meta.load_state = UNIT_LOADED,
                .type = SERVICE_SIMPLE,
        };
        Unit *u = UNIT(&s);

        for (i = 0; i < ELEMENTSOF(test_states); i++) {
                s.state = test_states[i];
                printf("\nWith collapsing for service state %s\n"
                       "=========================================\n", service_state_to_string(s.state));
                for (a = 0; a < _JOB_TYPE_MAX_MERGING; a++) {
                        for (b = 0; b < _JOB_TYPE_MAX_MERGING; b++) {

                                ab = a;
                                merged_ab = (job_type_merge_and_collapse(&ab, b, u) >= 0);

                                if (!job_type_is_mergeable(a, b)) {
                                        assert_se(!merged_ab);
                                        printf("Not mergeable: %s + %s\n", job_type_to_string(a), job_type_to_string(b));
                                        continue;
                                }

                                assert_se(merged_ab);
                                printf("%s + %s = %s\n", job_type_to_string(a), job_type_to_string(b), job_type_to_string(ab));

                                for (c = 0; c < _JOB_TYPE_MAX_MERGING; c++) {

                                        /* Verify transitivity of mergeability of job types */
                                        assert_se(!job_type_is_mergeable(a, b) ||
                                               !job_type_is_mergeable(b, c) ||
                                               job_type_is_mergeable(a, c));

                                        /* Verify that merged entries can be merged with the same entries
                                         * they can be merged with separately */
                                        assert_se(!job_type_is_mergeable(a, c) || job_type_is_mergeable(ab, c));
                                        assert_se(!job_type_is_mergeable(b, c) || job_type_is_mergeable(ab, c));

                                        /* Verify that if a merged with b is not mergeable with c, then
                                         * either a or b is not mergeable with c either. */
                                        assert_se(job_type_is_mergeable(ab, c) || !job_type_is_mergeable(a, c) || !job_type_is_mergeable(b, c));

                                        bc = b;
                                        if (job_type_merge_and_collapse(&bc, c, u) >= 0) {

                                                /* Verify associativity */

                                                ab_c = ab;
                                                assert_se(job_type_merge_and_collapse(&ab_c, c, u) == 0);

                                                bc_a = bc;
                                                assert_se(job_type_merge_and_collapse(&bc_a, a, u) == 0);

                                                a_bc = a;
                                                assert_se(job_type_merge_and_collapse(&a_bc, bc, u) == 0);

                                                assert_se(ab_c == bc_a);
                                                assert_se(ab_c == a_bc);

                                                printf("%s + %s + %s = %s\n", job_type_to_string(a), job_type_to_string(b), job_type_to_string(c), job_type_to_string(ab_c));
                                        }
                                }
                        }
                }
        }


        return 0;
}
예제 #26
0
static long
sdwrite(Chan* c, void* a, long n, vlong off)
{
	char *f0;
	int i;
	uvlong end, start;
	Cmdbuf *cb;
	SDifc *ifc;
	SDreq *req;
	SDunit *unit;
	SDev *sdev;

	switch(TYPE(c->qid)){
	default:
		error(Eperm);
	case Qtopctl:
		cb = parsecmd(a, n);
		if(waserror()){
			free(cb);
			nexterror();
		}
		if(cb->nf == 0)
			error("empty control message");
		f0 = cb->f[0];
		cb->f++;
		cb->nf--;
		if(strcmp(f0, "config") == 0){
			/* wormhole into ugly legacy interface */
			legacytopctl(cb);
			poperror();
			free(cb);
			break;
		}
		/*
		 * "ata arg..." invokes sdifc[i]->wtopctl(nil, cb),
		 * where sdifc[i]->name=="ata" and cb contains the args.
		 */
		ifc = nil;
		sdev = nil;
		for(i=0; sdifc[i]; i++){
			if(strcmp(sdifc[i]->name, f0) == 0){
				ifc = sdifc[i];
				sdev = nil;
				goto subtopctl;
			}
		}
		/*
		 * "sd1 arg..." invokes sdifc[i]->wtopctl(sdev, cb),
		 * where sdifc[i] and sdev match controller letter "1",
		 * and cb contains the args.
		 */
		if(f0[0]=='s' && f0[1]=='d' && f0[2] && f0[3] == 0){
			if((sdev = sdgetdev(f0[2])) != nil){
				ifc = sdev->ifc;
				goto subtopctl;
			}
		}
		error("unknown interface");

	subtopctl:
		if(waserror()){
			if(sdev)
				decref(&sdev->r);
			nexterror();
		}
		if(ifc->wtopctl)
			ifc->wtopctl(sdev, cb);
		else
			error(Ebadctl);
		poperror();
		poperror();
		if (sdev)
			decref(&sdev->r);
		free(cb);
		break;

	case Qctl:
		cb = parsecmd(a, n);
		sdev = sdgetdev(DEV(c->qid));
		if(sdev == nil)
			error(Enonexist);
		unit = sdev->unit[UNIT(c->qid)];

		qlock(&unit->ctl);
		if(waserror()){
			qunlock(&unit->ctl);
			decref(&sdev->r);
			free(cb);
			nexterror();
		}
		if(unit->vers != c->qid.vers)
			error(Echange);

		if(cb->nf < 1)
			error(Ebadctl);
		if(strcmp(cb->f[0], "part") == 0){
			if(cb->nf != 4)
				error(Ebadctl);
			if(unit->sectors == 0 && !sdinitpart(unit))
				error(Eio);
			start = strtoull(cb->f[2], 0, 0);
			end = strtoull(cb->f[3], 0, 0);
			sdaddpart(unit, cb->f[1], start, end);
		}
		else if(strcmp(cb->f[0], "delpart") == 0){
			if(cb->nf != 2 || unit->part == nil)
				error(Ebadctl);
			sddelpart(unit, cb->f[1]);
		}
		else if(unit->dev->ifc->wctl)
			unit->dev->ifc->wctl(unit, cb);
		else
			error(Ebadctl);
		qunlock(&unit->ctl);
		decref(&sdev->r);
		poperror();
		free(cb);
		break;

	case Qraw:
		sdev = sdgetdev(DEV(c->qid));
		if(sdev == nil)
			error(Enonexist);
		unit = sdev->unit[UNIT(c->qid)];
		qlock(&unit->raw);
		if(waserror()){
			qunlock(&unit->raw);
			decref(&sdev->r);
			nexterror();
		}
		switch(unit->state){
		case Rawcmd:
			if(n < 6 || n > sizeof(req->cmd))
				error(Ebadarg);
			if((req = malloc(sizeof(SDreq))) == nil)
				error(Enomem);
			req->unit = unit;
			memmove(req->cmd, a, n);
			req->clen = n;
			req->flags = SDnosense;
			req->status = ~0;

			unit->req = req;
			unit->state = Rawdata;
			break;

		case Rawstatus:
			unit->state = Rawcmd;
			free(unit->req);
			unit->req = nil;
			error(Ebadusefd);

		case Rawdata:
			unit->state = Rawstatus;
			unit->req->write = 1;
			n = sdrio(unit->req, a, n);
		}
		qunlock(&unit->raw);
		decref(&sdev->r);
		poperror();
		break;
	case Qpart:
		return sdbio(c, 1, a, n, off);
	}

	return n;
}
예제 #27
0
파일: gsc.c 프로젝트: npe9/spin
int gscioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
{
    int unit = UNIT(minor(dev));
    struct gsc_unit *scu = unittab + unit;

    lprintf("gsc%d.ioctl: minor %d\n",
            unit, minor(dev));

    if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
    {
        lprintf("gsc%d.ioctl: unit was not attached successfully 0x04x\n",
                unit, scu->flags);
        return ENXIO;
    }

    switch(cmd) {
    case GSC_SRESSW:
        lprintf("gsc%d.ioctl:GSC_SRESSW\n", unit);
        if ( scu->flags & READING )
        {
            lprintf("gsc%d:ioctl on already reading unit\n", unit);
            return EBUSY;
        }
        scu->geometry = get_geometry(scu);
        return SUCCESS;
    case GSC_GRES:
        *(int *)data=geomtab[scu->geometry].dpi;
        lprintf("gsc%d.ioctl:GSC_GRES %ddpi\n", unit, *(int *)data);
        return SUCCESS;
    case GSC_GWIDTH:
        *(int *)data=geomtab[scu->geometry].dpl;
        lprintf("gsc%d.ioctl:GSC_GWIDTH %d\n", unit, *(int *)data);
        return SUCCESS;
    case GSC_SRES:
    case GSC_SWIDTH:
        lprintf("gsc%d.ioctl:GSC_SRES or GSC_SWIDTH %d\n",
                unit, *(int *)data);
        {   int g;
            struct gsc_geom geom = NEW_GEOM;
            if ( cmd == GSC_SRES )
                geom.dpi = *(int *)data;
            else
                geom.dpl = *(int *)data;
            if ( ( g = lookup_geometry(geom, scu) ) == INVALID )
                return EINVAL;
            scu->geometry = g;
            return SUCCESS;
        }
    case GSC_GHEIGHT:
        *(int *)data=scu->height;
        lprintf("gsc%d.ioctl:GSC_GHEIGHT %d\n", unit, *(int *)data);
        return SUCCESS;
    case GSC_SHEIGHT:
        lprintf("gsc%d.ioctl:GSC_SHEIGHT %d\n", unit, *(int *)data);
        if ( scu->flags & READING )
        {
            lprintf("gsc%d:ioctl on already reading unit\n", unit);
            return EBUSY;
        }
        scu->height=*(int *)data;
        return SUCCESS;
    case GSC_GBLEN:
        *(int *)data=scu->blen;
        lprintf("gsc%d.ioctl:GSC_GBLEN %d\n", unit, *(int *)data);
        return SUCCESS;
    case GSC_SBLEN:
        lprintf("gsc%d.ioctl:GSC_SBLEN %d\n", unit, *(int *)data);
        if (*(int *)data * geomtab[scu->geometry].dpl / 8 > MAX_BUFSIZE)
        {
            lprintf("gsc%d:ioctl buffer size too high\n", unit);
            return ENOMEM;
        }
        scu->blen=*(int *)data;
        return SUCCESS;
    case GSC_GBTIME:
        *(int *)data = scu->btime / hz;
        lprintf("gsc%d.ioctl:GSC_GBTIME %d\n", unit, *(int *)data);
        return SUCCESS;
    case GSC_SBTIME:
        scu->btime = *(int *)data * hz;
        lprintf("gsc%d.ioctl:GSC_SBTIME %d\n", unit, *(int *)data);
        return SUCCESS;
    default:
        return ENOTTY;
    }
}
예제 #28
0
파일: automount.c 프로젝트: teg/systemd
static void automount_trigger_notify(Unit *u, Unit *other) {
        Automount *a = AUTOMOUNT(u);
        int r;

        assert(a);
        assert(other);

        /* Filter out invocations with bogus state */
        if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT)
                return;

        /* Don't propagate state changes from the mount if we are already down */
        if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING))
                return;

        /* Propagate start limit hit state */
        if (other->start_limit_hit) {
                automount_enter_dead(a, AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT);
                return;
        }

        /* Don't propagate anything if there's still a job queued */
        if (other->job)
                return;

        /* The mount is successfully established */
        if (IN_SET(MOUNT(other)->state, MOUNT_MOUNTED, MOUNT_REMOUNTING)) {
                (void) automount_send_ready(a, a->tokens, 0);

                r = automount_start_expire(a);
                if (r < 0)
                        log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m");

                automount_set_state(a, AUTOMOUNT_RUNNING);
        }

        if (IN_SET(MOUNT(other)->state,
                   MOUNT_MOUNTING, MOUNT_MOUNTING_DONE,
                   MOUNT_MOUNTED, MOUNT_REMOUNTING,
                   MOUNT_MOUNTING_SIGTERM, MOUNT_MOUNTING_SIGKILL,
                   MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL,
                   MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL,
                   MOUNT_FAILED)) {

                (void) automount_send_ready(a, a->expire_tokens, -ENODEV);
        }

        if (MOUNT(other)->state == MOUNT_DEAD)
                (void) automount_send_ready(a, a->expire_tokens, 0);

        /* The mount is in some unhappy state now, let's unfreeze any waiting clients */
        if (IN_SET(MOUNT(other)->state,
                   MOUNT_DEAD, MOUNT_UNMOUNTING,
                   MOUNT_MOUNTING_SIGTERM, MOUNT_MOUNTING_SIGKILL,
                   MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL,
                   MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL,
                   MOUNT_FAILED)) {

                (void) automount_send_ready(a, a->tokens, -ENODEV);

                automount_set_state(a, AUTOMOUNT_WAITING);
        }
}