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; }
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; }
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; }
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; } }
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); }
// 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),
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); }
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; }
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; }
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); }
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; }
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; }
/* * 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; }
/* * 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; }
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; }
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; }
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; }
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); }
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); }
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; }
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; }
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); }
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); }
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); } }
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; }
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; }
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; } }
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); } }