int udev_node_mknod(struct udev_device *dev, const char *file, dev_t devnum, mode_t mode, uid_t uid, gid_t gid) { struct udev *udev = udev_device_get_udev(dev); struct stat stats; int preserve = 0; int err = 0; if (major(devnum) == 0) devnum = udev_device_get_devnum(dev); if (strcmp(udev_device_get_subsystem(dev), "block") == 0) mode |= S_IFBLK; else mode |= S_IFCHR; if (file == NULL) file = udev_device_get_devnode(dev); if (lstat(file, &stats) == 0) { if (((stats.st_mode & S_IFMT) == (mode & S_IFMT)) && (stats.st_rdev == devnum)) { info(udev, "preserve file '%s', because it has correct dev_t\n", file); preserve = 1; udev_selinux_lsetfilecon(udev, file, mode); /* update time stamp when we re-use the node, like on media change events */ utimes(file, NULL); } else { char file_tmp[UTIL_PATH_SIZE + sizeof(TMP_FILE_EXT)]; info(udev, "atomically replace existing file '%s'\n", file); util_strscpyl(file_tmp, sizeof(file_tmp), file, TMP_FILE_EXT, NULL); unlink(file_tmp); udev_selinux_setfscreatecon(udev, file_tmp, mode); err = mknod(file_tmp, mode, devnum); udev_selinux_resetfscreatecon(udev); if (err != 0) { err(udev, "mknod(%s, %#o, %u, %u) failed: %m\n", file_tmp, mode, major(devnum), minor(devnum)); goto exit; } err = rename(file_tmp, file); if (err != 0) { err(udev, "rename(%s, %s) failed: %m\n", file_tmp, file); unlink(file_tmp); } } } else { info(udev, "mknod(%s, %#o, (%u,%u))\n", file, mode, major(devnum), minor(devnum)); do { err = util_create_path(udev, file); if (err != 0 && err != -ENOENT) break; udev_selinux_setfscreatecon(udev, file, mode); err = mknod(file, mode, devnum); if (err != 0) err = -errno; udev_selinux_resetfscreatecon(udev); } while (err == -ENOENT); if (err != 0) { err(udev, "mknod(%s, %#o, (%u,%u) failed: %m\n", file, mode, major(devnum), minor(devnum)); goto exit; } } if (!preserve || stats.st_mode != mode) { info(udev, "chmod(%s, %#o)\n", file, mode); err = chmod(file, mode); if (err != 0) { err(udev, "chmod(%s, %#o) failed: %m\n", file, mode); goto exit; } } if (!preserve || stats.st_uid != uid || stats.st_gid != gid) { info(udev, "chown(%s, %u, %u)\n", file, uid, gid); err = chown(file, uid, gid); if (err != 0) { err(udev, "chown(%s, %u, %u) failed: %m\n", file, uid, gid); goto exit; } } exit: return err; }
int kbdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) { struct kbd_softc *k; struct kbd_state *ks; int error = 0; k = device_lookup_private(&kbd_cd, minor(dev)); ks = &k->k_state; switch (cmd) { case KIOCTRANS: /* Set translation mode */ /* We only support "raw" mode on /dev/kbd */ if (*(int *)data != TR_UNTRANS_EVENT) error = EINVAL; break; case KIOCGTRANS: /* Get translation mode */ /* We only support "raw" mode on /dev/kbd */ *(int *)data = TR_UNTRANS_EVENT; break; #ifdef KIOCGETKEY case KIOCGETKEY: /* Get keymap entry (old format) */ error = kbd_oldkeymap(ks, cmd, (struct okiockey *)data); break; #endif /* KIOCGETKEY */ case KIOCSKEY: /* Set keymap entry */ /* FALLTHROUGH */ case KIOCGKEY: /* Get keymap entry */ error = kbd_iockeymap(ks, cmd, (struct kiockeymap *)data); break; case KIOCCMD: /* Send a command to the keyboard */ /* pass it to the middle layer */ if (k->k_ops != NULL && k->k_ops->docmd != NULL) error = (*k->k_ops->docmd)(k, *(int *)data, 1); break; case KIOCTYPE: /* Get keyboard type */ *(int *)data = ks->kbd_id; break; case KIOCSDIRECT: /* Where to send input */ k->k_evmode = *(int *)data; break; case KIOCLAYOUT: /* Get keyboard layout */ *(int *)data = ks->kbd_layout; break; case KIOCSLED: /* Set keyboard LEDs */ /* pass the request to the middle layer */ if (k->k_ops != NULL && k->k_ops->setleds != NULL) error = (*k->k_ops->setleds)(k, *(char *)data, 1); break; case KIOCGLED: /* Get keyboard LEDs */ *(char *)data = ks->kbd_leds; break; case FIONBIO: /* we will remove this someday (soon???) */ break; case FIOASYNC: k->k_events.ev_async = (*(int *)data != 0); break; case FIOSETOWN: if (-*(int *)data != k->k_events.ev_io->p_pgid && *(int *)data != k->k_events.ev_io->p_pid) error = EPERM; break; case TIOCSPGRP: if (*(int *)data != k->k_events.ev_io->p_pgid) error = EPERM; break; default: error = ENOTTY; break; } return error; }
static int iir_ioctl(dev_t dev, u_long cmd, caddr_t cmdarg, int flags, d_thread_t * p) { GDT_DPRINTF(GDT_D_DEBUG, ("iir_ioctl() cmd 0x%lx\n",cmd)); #ifdef SDEV_PER_HBA int minor_no; struct gdt_softc *gdt; minor_no = minor(dev); gdt = gdt_minor2softc(minor_no); if (gdt == NULL) return (ENXIO); #endif ++gdt_stat.io_count_act; if (gdt_stat.io_count_act > gdt_stat.io_count_max) gdt_stat.io_count_max = gdt_stat.io_count_act; switch (cmd) { case GDT_IOCTL_GENERAL: { gdt_ucmd_t *ucmd; struct gdt_softc *gdt; int lock; ucmd = (gdt_ucmd_t *)cmdarg; gdt = gdt_minor2softc(ucmd->io_node); if (gdt == NULL) return (ENXIO); lock = splcam(); TAILQ_INSERT_TAIL(&gdt->sc_ucmd_queue, ucmd, links); ucmd->complete_flag = FALSE; splx(lock); gdt_next(gdt); if (!ucmd->complete_flag) (void) tsleep((void *)ucmd, PCATCH | PRIBIO, "iirucw", 0); break; } case GDT_IOCTL_DRVERS: *(int *)cmdarg = (IIR_DRIVER_VERSION << 8) | IIR_DRIVER_SUBVERSION; break; case GDT_IOCTL_CTRTYPE: { gdt_ctrt_t *p; struct gdt_softc *gdt; p = (gdt_ctrt_t *)cmdarg; gdt = gdt_minor2softc(p->io_node); if (gdt == NULL) return (ENXIO); p->oem_id = 0x8000; p->type = 0xfd; p->info = (gdt->sc_bus << 8) | (gdt->sc_slot << 3); p->ext_type = 0x6000 | gdt->sc_subdevice; p->device_id = gdt->sc_device; p->sub_device_id = gdt->sc_subdevice; break; } case GDT_IOCTL_OSVERS: { gdt_osv_t *p; p = (gdt_osv_t *)cmdarg; p->oscode = 10; p->version = osrelease[0] - '0'; if (osrelease[1] == '.') p->subversion = osrelease[2] - '0'; else p->subversion = 0; if (osrelease[3] == '.') p->revision = osrelease[4] - '0'; else p->revision = 0; strcpy(p->name, ostype); break; } case GDT_IOCTL_CTRCNT: *(int *)cmdarg = gdt_cnt; break; case GDT_IOCTL_EVENT: { gdt_event_t *p; int lock; p = (gdt_event_t *)cmdarg; if (p->erase == 0xff) { if (p->dvr.event_source == GDT_ES_TEST) p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.test); else if (p->dvr.event_source == GDT_ES_DRIVER) p->dvr.event_data.size= sizeof(p->dvr.event_data.eu.driver); else if (p->dvr.event_source == GDT_ES_SYNC) p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.sync); else p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.async); lock = splcam(); gdt_store_event(p->dvr.event_source, p->dvr.event_idx, &p->dvr.event_data); splx(lock); } else if (p->erase == 0xfe) { lock = splcam(); gdt_clear_events(); splx(lock); } else if (p->erase == 0) { p->handle = gdt_read_event(p->handle, &p->dvr); } else { gdt_readapp_event((u_int8_t)p->erase, &p->dvr); } break; } case GDT_IOCTL_STATIST: { gdt_statist_t *p; p = (gdt_statist_t *)cmdarg; bcopy(&gdt_stat, p, sizeof(gdt_statist_t)); break; } default: break; } --gdt_stat.io_count_act; return (0); }
/* * Arranges output according to a single parsed format substring. */ int format1(const struct stat *st, const char *file, const char *fmt, int flen, char *buf, size_t blen, int flags, int size, int prec, int ofmt, int hilo, int what) { u_int64_t data; char *stmp, lfmt[24], tmp[20]; const char *sdata; char smode[12], sid[12], path[PATH_MAX + 4]; struct passwd *pw; struct group *gr; const struct timespec *tsp; struct timespec ts; struct tm *tm; int l, small, formats; tsp = NULL; formats = 0; small = 0; /* * First, pick out the data and tweak it based on hilo or * specified output format (symlink output only). */ switch (what) { case SHOW_st_dev: case SHOW_st_rdev: small = (sizeof(st->st_dev) == 4); data = (what == SHOW_st_dev) ? st->st_dev : st->st_rdev; #if HAVE_DEVNAME sdata = (what == SHOW_st_dev) ? devname(st->st_dev, S_IFBLK) : devname(st->st_rdev, S_ISCHR(st->st_mode) ? S_IFCHR : S_ISBLK(st->st_mode) ? S_IFBLK : 0U); if (sdata == NULL) sdata = "???"; #endif /* HAVE_DEVNAME */ if (hilo == HIGH_PIECE) { data = major(data); hilo = 0; } else if (hilo == LOW_PIECE) { data = minor((unsigned)data); hilo = 0; } formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX | #if HAVE_DEVNAME FMTF_STRING; #else /* HAVE_DEVNAME */ 0; #endif /* HAVE_DEVNAME */ if (ofmt == 0) ofmt = FMTF_UNSIGNED; break; case SHOW_st_ino: small = (sizeof(st->st_ino) == 4); data = st->st_ino; sdata = NULL; formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX; if (ofmt == 0) ofmt = FMTF_UNSIGNED; break; case SHOW_st_mode: small = (sizeof(st->st_mode) == 4); data = st->st_mode; strmode(st->st_mode, smode); stmp = smode; l = strlen(stmp); if (stmp[l - 1] == ' ') stmp[--l] = '\0'; if (hilo == HIGH_PIECE) { data >>= 12; stmp += 1; stmp[3] = '\0'; hilo = 0; } else if (hilo == MIDDLE_PIECE) {
void dodumpsys(void) { const struct bdevsw *bdev; int dumpend, psize; int error; if (dumpdev == NODEV) return; bdev = bdevsw_lookup(dumpdev); if (bdev == NULL || bdev->d_psize == NULL) return; /* * For dumps during autoconfiguration, * if dump device has already configured... */ if (dumpsize == 0) cpu_dumpconf(); if (dumplo <= 0 || dumpsize == 0) { printf("\ndump to dev %u,%u not possible\n", major(dumpdev), minor(dumpdev)); return; } printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev), minor(dumpdev), dumplo); psize = (*bdev->d_psize)(dumpdev); printf("dump "); if (psize == -1) { printf("area unavailable\n"); return; } #if 0 /* XXX this doesn't work. grr. */ /* toss any characters present prior to dump */ while (sget() != NULL); /*syscons and pccons differ */ #endif dump_seg_prep(); dumpend = dumplo + btodb(dump_header_size) + ctod(dump_npages); if (dumpend > psize) { printf("failed: insufficient space (%d < %d)\n", psize, dumpend); goto failed; } dump_header_start(); if ((error = cpu_dump()) != 0) goto err; if ((error = dump_header_finish()) != 0) goto err; if (dump_header_blkno != dumplo + btodb(dump_header_size)) { printf("BAD header size (%ld [written] != %ld [expected])\n", (long)(dump_header_blkno - dumplo), (long)btodb(dump_header_size)); goto failed; } dump_totalbytesleft = roundup(ptoa(dump_npages), BYTES_PER_DUMP); error = dump_seg_iter(dumpsys_seg); if (error == 0 && dump_header_blkno != dumpend) { printf("BAD dump size (%ld [written] != %ld [expected])\n", (long)(dumpend - dumplo), (long)(dump_header_blkno - dumplo)); goto failed; } err: switch (error) { case ENXIO: printf("device bad\n"); break; case EFAULT: printf("device not ready\n"); break; case EINVAL: printf("area improper\n"); break; case EIO: printf("i/o error\n"); break; case EINTR: printf("aborted from console\n"); break; case 0: printf("succeeded\n"); break; default: printf("error %d\n", error); break; } failed: printf("\n\n"); delay(5000000); /* 5 seconds */ }
int wsmouseioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { return (wsmousedoioctl(wsmouse_cd.cd_devs[minor(dev)], cmd, data, flag, p)); }
/* ALmost the same of entry_print_data in gfunc.c, but * not quite as we don't don't use FILE* structs here * for instance. TODO: integrate the two functions? * entry_print_data() */ gint rdup_write_header(struct rdup * e) { char *out; char t; if (S_ISDIR(e->f_mode)) { t = 'd'; } else if (S_ISCHR(e->f_mode)) { t = 'c'; } else if (S_ISBLK(e->f_mode)) { t = 'b'; } else if (S_ISFIFO(e->f_mode)) { t = 'p'; } else if (S_ISSOCK(e->f_mode)) { t = 's'; } else if (S_ISLNK(e->f_mode)) { t = 'l'; } else { if (e->f_lnk == 1) t = 'h'; else t = '-'; } if (t == 'b' || t == 'c') { /* device */ out = g_strdup_printf("%c%c %.4o %ld %ld %s %ld %s %ld %d,%d\n%s", e->plusmin == PLUS ? '+' : '-', t, (int)e->f_mode & 07777, (unsigned long)e->f_mtime, (unsigned long)e->f_uid, e->f_user, (unsigned long)e->f_gid, e->f_group, (unsigned long)e->f_name_size, (unsigned int)major(e->f_rdev), (unsigned int)minor(e->f_rdev), e->f_name); } else if (t == 'l' || t == 'h') { /* link */ gchar *n; n = g_strdup_printf("%s -> %s", e->f_name, e->f_target); e->f_name_size = strlen(n); out = g_strdup_printf("%c%c %.4o %ld %ld %s %ld %s %ld %zd\n%s", e->plusmin == PLUS ? '+' : '-', t, (int)e->f_mode & 07777, (unsigned long)e->f_mtime, (unsigned long)e->f_uid, e->f_user, (unsigned long)e->f_gid, e->f_group, (unsigned long)e->f_name_size, (size_t) e->f_size, n); g_free(n); } else { out = g_strdup_printf("%c%c %.4o %ld %ld %s %ld %s %ld %zd\n%s", e->plusmin == PLUS ? '+' : '-', t, (int)e->f_mode & 07777, (unsigned long)e->f_mtime, (unsigned long)e->f_uid, e->f_user, (unsigned long)e->f_gid, e->f_group, (unsigned long)e->f_name_size, (size_t) e->f_size, e->f_name); } if (sig != 0) signal_abort(sig); if (write(1, out, strlen(out)) == -1) { msg(_("Failed to write to stdout: %s"), strerror(errno)); return -1; } g_free(out); return 0; }
/* * find a mnttab entry that has the same dev as the supplied dev, * returning it and a non-zero value if found, else returning 0 * * this is just like getmntany(), except that it scans based on st_rdev, * and it even finds different slices on the same device/unit (thanx to * code copied from format.c) */ static int vol_getmntdev(FILE *fp, struct mnttab *mp, dev_t dev, struct dk_cinfo *ip) { int fd; /* dev-in-question fd */ struct stat64 sb; /* dev-in-question stat struct */ int ret_val = 0; /* default value: no match found */ char *cn; /* char pathname */ struct dk_cinfo dkinfo; /* for testing for slices */ #ifdef DEBUG denter( "vol_getmntdev: entering for %d.%d, ctype/cnum/unit = %d/%d/%d\n", (int)major(dev), (int)minor(dev), ip->dki_ctype, ip->dki_cnum, ip->dki_unit); #endif /* reset the mnttab -- just in case */ rewind(fp); /* scan each entry in mnttab */ while (getmntent(fp, mp) == 0) { /* don't even try unless it's a local pathname */ if (mp->mnt_special[0] != '/') { continue; } /* get char pathname */ if ((cn = volmgt_getfullrawname(mp->mnt_special)) == NULL) { continue; } if (cn[0] == NULLC) { free(cn); continue; /* couldn't get raw name */ } /* open the device */ if ((fd = open(cn, O_RDONLY|O_NDELAY)) < 0) { /* if we can't open it *assume* it's not a match */ free(cn); continue; } /* stat the device */ if (fstat64(fd, &sb) < 0) { free(cn); (void) close(fd); continue; /* ain't there: can't be a match */ } /* ensure we have a spcl device (a double check) */ if (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode)) { free(cn); (void) close(fd); continue; } /* (almost) finally -- check the dev_t for equality */ if (sb.st_rdev == dev) { ret_val = 1; /* match found! */ free(cn); (void) close(fd); break; } /* * check that the major numbers match, since if they * don't then there's no reason to use the DKIOCINFO * ioctl to see if we have to major/minor pairs that * really point to the same device */ if (major(sb.st_rdev) != major(dev)) { /* no use continuing, since major devs are different */ free(cn); (void) close(fd); continue; } /* one last check -- for diff. slices of the same dev/unit */ if (ioctl(fd, DKIOCINFO, &dkinfo) < 0) { free(cn); (void) close(fd); continue; } free(cn); /* all done with raw pathname */ (void) close(fd); /* all done with file descriptor */ /* if ctrler type/number and unit match, it's a match */ if ((ip->dki_ctype == dkinfo.dki_ctype) && (ip->dki_cnum == dkinfo.dki_cnum) && (ip->dki_unit == dkinfo.dki_unit)) { /* * even though minor numbers differ we have a * match */ ret_val = 1; break; } /* go around again */ } return (ret_val); }
/* Store at most BUFLEN characters of the pathname of the slave pseudo terminal associated with the master FD is open on in BUF. Return 0 on success, otherwise an error number. */ int __ptsname_r (int fd, char *buf, size_t buflen) { int save_errno = errno; int err; struct stat st; if (buf == NULL) { __set_errno (EINVAL); return EINVAL; } #if defined __sun /* Solaris */ if (fstat (fd, &st) < 0) return errno; if (!(S_ISCHR (st.st_mode) && major (st.st_rdev) == 0)) { errno = ENOTTY; return errno; } { /* Master ptys can be recognized through a STREAMS ioctl. See "STREAMS-based Pseudo-Terminal Subsystem" <http://docs.oracle.com/cd/E18752_01/html/816-4855/termsub15-44781.html> and "STREAMS ioctl commands" <http://docs.oracle.com/cd/E18752_01/html/816-5177/streamio-7i.html> */ struct strioctl ioctl_arg; ioctl_arg.ic_cmd = ISPTM; ioctl_arg.ic_timout = 0; ioctl_arg.ic_len = 0; ioctl_arg.ic_dp = NULL; if (ioctl (fd, I_STR, &ioctl_arg) < 0) { errno = ENOTTY; return errno; } } { char tmpbuf[9 + 10 + 1]; int n = sprintf (tmpbuf, "/dev/pts/%u", minor (st.st_rdev)); if (n >= buflen) { errno = ERANGE; return errno; } memcpy (buf, tmpbuf, n + 1); } #elif defined _AIX || defined __osf__ /* AIX, OSF/1 */ /* This implementation returns /dev/pts/N, like ptsname() does. Whereas the generic implementation below returns /dev/ttypN. Both are correct, but let's be consistent with ptsname(). */ if (fstat (fd, &st) < 0) return errno; if (!S_ISCHR (st.st_mode)) { errno = ENOTTY; return errno; } { int ret; int dev; char tmpbuf[9 + 10 + 1]; int n; # ifdef _AIX ret = ioctl (fd, ISPTM, &dev); # endif # ifdef __osf__ ret = ioctl (fd, ISPTM, NULL); dev = ret; # endif if (ret < 0) { errno = ENOTTY; return errno; } n = sprintf (tmpbuf, "/dev/pts/%u", minor (dev)); if (n >= buflen) { errno = ERANGE; return errno; } memcpy (buf, tmpbuf, n + 1); } #else if (!__isatty (fd)) { #if ISATTY_FAILS_WITHOUT_SETTING_ERRNO && defined F_GETFL /* IRIX, Solaris */ /* Set errno. */ if (fcntl (fd, F_GETFL) != -1) errno = ENOTTY; #else /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY). */ #endif return errno; } if (buflen < strlen (_PATH_TTY) + 3) { __set_errno (ERANGE); return ERANGE; } err = __ttyname_r (fd, buf, buflen); if (err != 0) { __set_errno (err); return errno; } if (strncmp(buf, "/dev/pts/", strlen("/dev/pts/")) != 0) buf[sizeof (_PATH_DEV) - 1] = 't'; #endif if (__stat (buf, &st) < 0) return errno; __set_errno (save_errno); return 0; }
static int read_initfile(const char *initfile) { struct initline *p; FILE *f; char *buf = NULL; size_t buf_len = 0; int i,j,k; char *ptr, *getty; #ifdef SPECIAL_CONSOLE_TERM char tty[50]; struct stat stb; #endif char *termenv, *getenv(); termenv = getenv("TERM"); /* set by kernel */ /* termenv = "vt100"; */ i = numcmd; if (!(f = fopen(initfile, "r"))) return 1; while(!feof(f)) { if (i+2 == inittab_size) { /* need to realloc inittab */ inittab_size += NUMCMD; inittab = realloc(inittab, inittab_size * sizeof(struct initline)); if (!inittab) { /* failure case - what do you do if init fails? */ err("malloc failed"); _exit(1); } } if (getline(&buf, &buf_len, f) == -1) break; for(k = 0; k < buf_len && buf[k]; k++) { if(buf[k] == '#') { buf[k] = '\0'; break; } } if(buf[0] == '\0' || buf[0] == '\n') continue; p = inittab + i; init_itab(p); p->line = strdup(buf); p->fullline = strdup(buf); if (!p->line || !p->fullline) { err("Not memory to allocate inittab entry"); clear_itab(p); continue; } ptr = strtok(p->line, ":"); if (!ptr) { err("Missing TTY/ID field in inittab"); clear_itab(p); continue; } strncpy(p->tty, ptr, 9); //p->tty[9] = '\0'; ptr = strtok(NULL, ":"); if (!ptr) { err("Missing TERMTYPE field in inittab"); clear_itab(p); continue; } strncpy(p->termcap, ptr, 29); //p->termcap[29] = '\0'; getty = strtok(NULL, " \t\n"); if (!getty) { err("Missing PROCESS field in inittab"); clear_itab(p); continue; } add_tok(p, getty); j = 1; while((ptr = strtok(NULL, " \t\n"))) add_tok(p, ptr); #ifdef SPECIAL_CONSOLE_TERM /* special-case termcap for the console ttys */ strcpy(tty, "/dev/"); strcat(tty, p->tty); if(!termenv || stat(tty, &stb) < 0) { err("no TERM or cannot stat tty\n"); } else { /* is it a console tty? */ if(major(stb.st_rdev) == 4 && minor(stb.st_rdev) < 64) { strncpy(p->termcap, termenv, 30); p->termcap[29] = 0; } } #endif i++; } if (buf) free(buf); fclose(f); numcmd = i; return 0; }
bool VersionString::isNextVersion(const VersionString& nextVersionCandidate) const { VersionString variantOnThis(str()); VersionString variantOnCandidate = nextVersionCandidate; if (variantOnCandidate <= variantOnThis) { return false; } // now know nextVersionCandidate > this if (build() && fidelityEqual(nextVersionCandidate)) { // true if versions except for build number are equal variantOnThis = VersionString(major(),minor(),patch().get()); variantOnCandidate = VersionString(nextVersionCandidate.major(), nextVersionCandidate.minor(), nextVersionCandidate.patch().get()); if (variantOnCandidate == variantOnThis) { return true; } } else { // strip out build numbers as needed, because that is not the level at which the // versions differ if (build()) { variantOnThis = VersionString(major(),minor(),patch().get()); } if (nextVersionCandidate.build()) { variantOnCandidate = VersionString(nextVersionCandidate.major(), nextVersionCandidate.minor(), nextVersionCandidate.patch().get()); } } // now have major.minor or major.minor.patch for both if (variantOnThis.patch()) { if (variantOnCandidate.patch()) { VersionString thisIncremented(major(),minor(),patch().get() + 1); if (variantOnCandidate == thisIncremented) { return true; } // candidate has patch, but is not next patch version. to be next version, // must have patch == 0 if (variantOnCandidate.patch().get() != 0) { return false; } } } // now major.minor.patch v. major.minor or major.minor.patch v. major.minor.0 // strip out patch numbers if (variantOnThis.patch()) { variantOnThis = VersionString(variantOnThis.major(),variantOnThis.minor()); } if (variantOnCandidate.patch()) { variantOnCandidate = VersionString(variantOnCandidate.major(),variantOnCandidate.minor()); } // minor increment VersionString thisIncremented(variantOnThis.major(),variantOnThis.minor() + 1); if (variantOnCandidate == thisIncremented) { return true; } // major increment thisIncremented = VersionString(variantOnThis.major() + 1,0); if (variantOnCandidate == thisIncremented) { return true; } return false; }
int main(int argc, char *argv[]) { int c, devfd; char *protostore; long protosize; struct stat disksb, bootsb; struct disklabel dl; daddr64_t partoffset; #define BBPAD 0x1e0 struct bb { char bb_pad[BBPAD]; /* disklabel lives in here, actually */ long bb_secsize; /* size of secondary boot block */ long bb_secstart; /* start of secondary boot block */ long bb_flags; /* unknown; always zero */ long bb_cksum; /* checksum of the boot block, as longs. */ } bb; long *lp, *ep; while ((c = getopt(argc, argv, "vns:e:")) != -1) { switch (c) { case 'n': /* Do not actually write the bootblock to disk */ nowrite = 1; break; case 'v': /* Chat */ verbose = 1; break; case 's': isofsblk = atoi(optarg); break; case 'e': isofseblk = atoi(optarg); break; default: usage(); } } if (argc - optind < 3) usage(); boot = argv[optind]; proto = argv[optind + 1]; dev = argv[optind + 2]; if (verbose) { (void)printf("boot: %s\n", boot); (void)printf("proto: %s\n", proto); (void)printf("device: %s\n", dev); } /* Load proto blocks into core */ if ((protostore = loadprotoblocks(proto, &protosize)) == NULL) exit(1); /* Open and check raw disk device */ if ((devfd = opendev(dev, O_RDONLY, OPENDEV_PART, &dev)) < 0) err(1, "open: %s", dev); if (fstat(devfd, &disksb) == -1) err(1, "fstat: %s", dev); if (!S_ISCHR(disksb.st_mode)) errx(1, "%s must be a character device node", dev); if ((minor(disksb.st_rdev) % getmaxpartitions()) != getrawpartition()) errx(1, "%s must be the raw partition", dev); /* Extract and load block numbers */ if (stat(boot, &bootsb) == -1) err(1, "stat: %s", boot); if (!S_ISREG(bootsb.st_mode)) errx(1, "%s must be a regular file", boot); if ((minor(disksb.st_rdev) / getmaxpartitions()) != (minor(bootsb.st_dev) / getmaxpartitions())) errx(1, "%s must be somewhere on %s", boot, dev); /* * Find the offset of the secondary boot block's partition * into the disk. If disklabels not supported, assume zero. */ if (ioctl(devfd, DIOCGDINFO, &dl) != -1) { partoffset = DL_GETPOFFSET(&dl.d_partitions[minor(bootsb.st_dev) % getmaxpartitions()]); } else { if (errno != ENOTTY) err(1, "read disklabel: %s", dev); warnx("couldn't read label from %s, using part offset of 0", dev); partoffset = 0; } if (verbose) (void)printf("%s partition offset = 0x%lx\n", boot, partoffset); /* Sync filesystems (make sure boot's block numbers are stable) */ sync(); sleep(2); sync(); sleep(2); if (loadblocknums(boot, devfd, partoffset) != 0) exit(1); (void)close(devfd); if (nowrite) return 0; #if 0 /* Write patched proto bootblocks into the superblock */ if (protosize > SBSIZE - DEV_BSIZE) errx(1, "proto bootblocks too big"); #endif if ((devfd = opendev(dev, O_RDWR, OPENDEV_PART, &dev)) < 0) err(1, "open: %s", dev); if (lseek(devfd, DEV_BSIZE, SEEK_SET) != DEV_BSIZE) err(1, "lseek bootstrap"); if (write(devfd, protostore, protosize) != protosize) err(1, "write bootstrap"); if (lseek(devfd, 0, SEEK_SET) != 0) err(1, "lseek label"); if (read(devfd, &bb, sizeof (bb)) != sizeof (bb)) err(1, "read label"); bb.bb_secsize = 15; bb.bb_secstart = 1; bb.bb_flags = 0; bb.bb_cksum = 0; for (lp = (long *)&bb, ep = &bb.bb_cksum; lp < ep; lp++) bb.bb_cksum += *lp; if (lseek(devfd, 0, SEEK_SET) != 0) err(1, "lseek label 2"); if (write(devfd, &bb, sizeof bb) != sizeof bb) err(1, "write label "); (void)close(devfd); return 0; }
/* Return value will become exit code. * It's ok to exit instead of return. */ static NOINLINE int cpio_o(void) { static const char trailer[] ALIGN1 = "TRAILER!!!"; struct name_s { struct name_s *next; char name[1]; }; struct inodes_s { struct inodes_s *next; struct name_s *names; struct stat st; }; struct inodes_s *links = NULL; off_t bytes = 0; /* output bytes count */ while (1) { const char *name; char *line; struct stat st; line = (option_mask32 & CPIO_OPT_NUL_TERMINATED) ? bb_get_chunk_from_file(stdin, NULL) : xmalloc_fgetline(stdin); if (line) { /* Strip leading "./[./]..." from the filename */ name = line; while (name[0] == '.' && name[1] == '/') { while (*++name == '/') continue; } if (!*name) { /* line is empty */ free(line); continue; } if ((option_mask32 & CPIO_OPT_DEREF) ? stat(name, &st) : lstat(name, &st) ) { abort_cpio_o: bb_simple_perror_msg_and_die(name); } if (!(S_ISLNK(st.st_mode) || S_ISREG(st.st_mode))) st.st_size = 0; /* paranoia */ /* Store hardlinks for later processing, dont output them */ if (!S_ISDIR(st.st_mode) && st.st_nlink > 1) { struct name_s *n; struct inodes_s *l; /* Do we have this hardlink remembered? */ l = links; while (1) { if (l == NULL) { /* Not found: add new item to "links" list */ l = xzalloc(sizeof(*l)); l->st = st; l->next = links; links = l; break; } if (l->st.st_ino == st.st_ino) { /* found */ break; } l = l->next; } /* Add new name to "l->names" list */ n = xmalloc(sizeof(*n) + strlen(name)); strcpy(n->name, name); n->next = l->names; l->names = n; free(line); continue; } } else { /* line == NULL: EOF */ next_link: if (links) { /* Output hardlink's data */ st = links->st; name = links->names->name; links->names = links->names->next; /* GNU cpio is reported to emit file data * only for the last instance. Mimic that. */ if (links->names == NULL) links = links->next; else st.st_size = 0; /* NB: we leak links->names and/or links, * this is intended (we exit soon anyway) */ } else { /* If no (more) hardlinks to output, * output "trailer" entry */ name = trailer; /* st.st_size == 0 is a must, but for uniformity * in the output, we zero out everything */ memset(&st, 0, sizeof(st)); /* st.st_nlink = 1; - GNU cpio does this */ } } bytes += printf("070701" "%08X%08X%08X%08X%08X%08X%08X" "%08X%08X%08X%08X" /* GNU cpio uses uppercase hex */ /* strlen+1: */ "%08X" /* chksum: */ "00000000" /* (only for "070702" files) */ /* name,NUL: */ "%s%c", (unsigned)(uint32_t) st.st_ino, (unsigned)(uint32_t) st.st_mode, (unsigned)(uint32_t) st.st_uid, (unsigned)(uint32_t) st.st_gid, (unsigned)(uint32_t) st.st_nlink, (unsigned)(uint32_t) st.st_mtime, (unsigned)(uint32_t) st.st_size, (unsigned)(uint32_t) major(st.st_dev), (unsigned)(uint32_t) minor(st.st_dev), (unsigned)(uint32_t) major(st.st_rdev), (unsigned)(uint32_t) minor(st.st_rdev), (unsigned)(strlen(name) + 1), name, '\0'); bytes = cpio_pad4(bytes); if (st.st_size) { if (S_ISLNK(st.st_mode)) { char *lpath = xmalloc_readlink_or_warn(name); if (!lpath) goto abort_cpio_o; bytes += printf("%s", lpath); free(lpath); } else { /* S_ISREG */ int fd = xopen(name, O_RDONLY); fflush_all(); /* We must abort if file got shorter too! */ bb_copyfd_exact_size(fd, STDOUT_FILENO, st.st_size); bytes += st.st_size; close(fd); } bytes = cpio_pad4(bytes); } if (!line) { if (name != trailer) goto next_link; /* TODO: GNU cpio pads trailer to 512 bytes, do we want that? */ return EXIT_SUCCESS; } free(line); } /* end of "while (1)" */ }
inline bool DeviceInfo::supports(FeatureSet feature_set) const { int version = major() * 10 + minor(); return version >= feature_set; }
static Eina_Bool _ecore_drm_logind_vt_setup(Ecore_Drm_Device *dev) { struct stat st; char buff[64]; struct vt_mode vtmode = { 0 }; snprintf(buff, sizeof(buff), "/dev/tty%d", dev->vt); buff[sizeof(buff) - 1] = 0; dev->tty.fd = open(buff, (O_RDWR | O_CLOEXEC | O_NONBLOCK)); if (dev->tty.fd < 0) { ERR("Could not open VT %s %m", buff); return EINA_FALSE; } if ((fstat(dev->tty.fd, &st) == -1) || (major(st.st_rdev) != TTY_MAJOR) || (minor(st.st_rdev) <= 0) || (minor(st.st_rdev) >= 64)) { ERR("TTY %s is not a virtual terminal", buff); goto stat_err; } if (ioctl(dev->tty.fd, KDGKBMODE, &dev->tty.kbd_mode) < 0) { ERR("Could not read keyboard mode of %s: %m", buff); dev->tty.kbd_mode = K_UNICODE; } else if (dev->tty.kbd_mode == K_OFF) dev->tty.kbd_mode = K_UNICODE; if ((ioctl(dev->tty.fd, KDSKBMUTE, 1) < 0) && (ioctl(dev->tty.fd, KDSKBMODE, K_OFF) < 0)) { ERR("Could not set K_OFF keyboard mode on %s: %m", buff); goto stat_err; } if (ioctl(dev->tty.fd, KDSETMODE, KD_GRAPHICS) < 0) { ERR("Could not set KD_GRAPHICS mode on %s: %m", buff); goto kbdmode_err; } vtmode.mode = VT_PROCESS; vtmode.waitv = 0; vtmode.relsig = SIGUSR1; vtmode.acqsig = SIGUSR2; if (ioctl(dev->tty.fd, VT_SETMODE, &vtmode) < 0) { ERR("Could not take over virtual terminal: %m"); goto mode_err; } return EINA_TRUE; mode_err: ioctl(dev->tty.fd, KDSETMODE, KD_TEXT); kbdmode_err: ioctl(dev->tty.fd, KDSKBMUTE, 0); ioctl(dev->tty.fd, KDSKBMODE, dev->tty.kbd_mode); stat_err: close(dev->tty.fd); return EINA_FALSE; }
int wskbdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) { return (wskbd_do_ioctl(device_lookup(&wskbd_cd, minor(dev)), cmd, data, flag,l)); }
void xf86OpenConsole(void) { int i, fd = -1, ret, current_vt = -1; struct vt_mode VT; struct vt_stat vts; struct stat st; MessageType from = X_PROBED; const char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; if (serverGeneration == 1) { /* * setup the virtual terminal manager */ if (xf86Info.vtno != -1) { from = X_CMDLINE; } else { i = 0; while (tty0[i] != NULL) { if ((fd = open(tty0[i], O_WRONLY, 0)) >= 0) break; i++; } if (fd < 0) FatalError("xf86OpenConsole: Cannot open /dev/tty0 (%s)\n", strerror(errno)); if (xf86Info.ShareVTs) { SYSCALL(ret = ioctl(fd, VT_GETSTATE, &vts)); if (ret < 0) FatalError("xf86OpenConsole: Cannot find the current" " VT (%s)\n", strerror(errno)); xf86Info.vtno = vts.v_active; } else { SYSCALL(ret = ioctl(fd, VT_OPENQRY, &xf86Info.vtno)); if (ret < 0) FatalError("xf86OpenConsole: Cannot find a free VT: " "%s\n", strerror(errno)); if (xf86Info.vtno == -1) FatalError("xf86OpenConsole: Cannot find a free VT\n"); } close(fd); } xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno); /* Some of stdin / stdout / stderr maybe redirected to a file */ for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) { ret = fstat(i, &st); if (ret == 0 && S_ISCHR(st.st_mode) && major(st.st_rdev) == 4) { current_vt = minor(st.st_rdev); break; } } if (!KeepTty && current_vt == xf86Info.vtno) { xf86Msg(X_PROBED, "controlling tty is VT number %d, auto-enabling KeepTty\n", current_vt); KeepTty = TRUE; } if (!KeepTty) { pid_t ppid = getppid(); pid_t ppgid; ppgid = getpgid(ppid); /* * change to parent process group that pgid != pid so * that setsid() doesn't fail and we become process * group leader */ if (setpgid(0, ppgid) < 0) xf86Msg(X_WARNING, "xf86OpenConsole: setpgid failed: %s\n", strerror(errno)); /* become process group leader */ if ((setsid() < 0)) xf86Msg(X_WARNING, "xf86OpenConsole: setsid failed: %s\n", strerror(errno)); } i = 0; while (vcs[i] != NULL) { snprintf(vtname, sizeof(vtname), vcs[i], xf86Info.vtno); /* /dev/tty1-64 */ if ((xf86Info.consoleFd = open(vtname, O_RDWR | O_NDELAY, 0)) >= 0) break; i++; } if (xf86Info.consoleFd < 0) FatalError("xf86OpenConsole: Cannot open virtual console" " %d (%s)\n", xf86Info.vtno, strerror(errno)); /* * Linux doesn't switch to an active vt after the last close of a vt, * so we do this ourselves by remembering which is active now. */ SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_GETSTATE, &vts)); if (ret < 0) xf86Msg(X_WARNING, "xf86OpenConsole: VT_GETSTATE failed: %s\n", strerror(errno)); else activeVT = vts.v_active; #if 0 if (!KeepTty) { /* * Detach from the controlling tty to avoid char loss */ if ((i = open("/dev/tty", O_RDWR)) >= 0) { SYSCALL(ioctl(i, TIOCNOTTY, 0)); close(i); } } #endif if (!xf86Info.ShareVTs) { struct termios nTty; /* * now get the VT. This _must_ succeed, or else fail completely. */ if (!switch_to(xf86Info.vtno, "xf86OpenConsole")) FatalError("xf86OpenConsole: Switching VT failed\n"); SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_GETMODE, &VT)); if (ret < 0) FatalError("xf86OpenConsole: VT_GETMODE failed %s\n", strerror(errno)); signal(SIGUSR1, xf86VTRequest); VT.mode = VT_PROCESS; VT.relsig = SIGUSR1; VT.acqsig = SIGUSR1; SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_SETMODE, &VT)); if (ret < 0) FatalError ("xf86OpenConsole: VT_SETMODE VT_PROCESS failed: %s\n", strerror(errno)); SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS)); if (ret < 0) FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed %s\n", strerror(errno)); tcgetattr(xf86Info.consoleFd, &tty_attr); SYSCALL(ioctl(xf86Info.consoleFd, KDGKBMODE, &tty_mode)); /* disable kernel special keys and buffering, new style */ SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSKBMUTE, 1)); if (ret < 0) { /* disable kernel special keys and buffering, old style */ SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSKBMODE, K_OFF)); if (ret < 0) { /* fine, just disable special keys */ SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW)); if (ret < 0) FatalError("xf86OpenConsole: KDSKBMODE K_RAW failed %s\n", strerror(errno)); /* ... and drain events, else the kernel gets angry */ xf86SetConsoleHandler(drain_console, NULL); } } nTty = tty_attr; nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); nTty.c_oflag = 0; nTty.c_cflag = CREAD | CS8; nTty.c_lflag = 0; nTty.c_cc[VTIME] = 0; nTty.c_cc[VMIN] = 1; cfsetispeed(&nTty, 9600); cfsetospeed(&nTty, 9600); tcsetattr(xf86Info.consoleFd, TCSANOW, &nTty); } } else { /* serverGeneration != 1 */ if (!xf86Info.ShareVTs && xf86Info.autoVTSwitch) { /* now get the VT */ if (!switch_to(xf86Info.vtno, "xf86OpenConsole")) FatalError("xf86OpenConsole: Switching VT failed\n"); } } }
static void show_stat(struct stat64 *sp, const char *what) { if (strcmp(what, "mode") == 0) printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS)); else if (strcmp(what, "inode") == 0) printf("%lld", (long long)sp->st_ino); else if (strcmp(what, "nlink") == 0) printf("%lld", (long long)sp->st_nlink); else if (strcmp(what, "uid") == 0) printf("%d", (int)sp->st_uid); else if (strcmp(what, "gid") == 0) printf("%d", (int)sp->st_gid); else if (strcmp(what, "size") == 0) printf("%lld", (long long)sp->st_size); else if (strcmp(what, "blocks") == 0) printf("%lld", (long long)sp->st_blocks); else if (strcmp(what, "atime") == 0) printf("%lld", (long long)sp->st_atime); else if (strcmp(what, "mtime") == 0) printf("%lld", (long long)sp->st_mtime); else if (strcmp(what, "ctime") == 0) printf("%lld", (long long)sp->st_ctime); #ifdef HAS_CHFLAGS else if (strcmp(what, "flags") == 0) printf("%s", flags2str(chflags_flags, (long long)sp->st_flags)); #endif else if (strcmp(what, "major") == 0) printf("%u", (unsigned int)major(sp->st_rdev)); else if (strcmp(what, "minor") == 0) printf("%u", (unsigned int)minor(sp->st_rdev)); else if (strcmp(what, "type") == 0) { switch (sp->st_mode & S_IFMT) { case S_IFIFO: printf("fifo"); break; case S_IFCHR: printf("char"); break; case S_IFDIR: printf("dir"); break; case S_IFBLK: printf("block"); break; case S_IFREG: printf("regular"); break; case S_IFLNK: printf("symlink"); break; case S_IFSOCK: printf("socket"); break; default: printf("unknown"); break; } } else { printf("unknown"); } }
void vinum_daemon(void) { int s; struct daemonq *request; curproc->p_flag |= P_INMEM | P_SYSTEM; /* we're a system process */ daemon_save_config(); /* start by saving the configuration */ daemonpid = curproc->p_pid; /* mark our territory */ while (1) { tsleep(&vinum_daemon, PRIBIO, "vinum", 0); /* wait for something to happen */ /* * It's conceivable that, as the result of an * I/O error, we'll be out of action long * enough that another daemon gets started. * That's OK, just give up gracefully. */ if (curproc->p_pid != daemonpid) { /* we've been ousted in our sleep */ if (daemon_options & daemon_verbose) log(LOG_INFO, "vinum: abdicating\n"); return; } while (daemonq != NULL) { /* we have work to do, */ s = splhigh(); /* don't get interrupted here */ request = daemonq; /* get the request */ daemonq = daemonq->next; /* and detach it */ if (daemonq == NULL) /* got to the end, */ dqend = NULL; /* no end any more */ splx(s); switch (request->type) { /* * We had an I/O error on a request. Go through the * request and try to salvage it */ case daemonrq_ioerror: if (daemon_options & daemon_verbose) { struct request *rq = request->info.rq; log(LOG_WARNING, "vinum: recovering I/O request: %p\n%s dev %d.%d, offset 0x%x, length %ld\n", rq, rq->bp->b_flags & B_READ ? "Read" : "Write", major(rq->bp->b_dev), minor(rq->bp->b_dev), rq->bp->b_blkno, rq->bp->b_bcount); } recover_io(request->info.rq); /* the failed request */ break; /* * Write the config to disk. We could end up with * quite a few of these in a row. Only honour the * last one */ case daemonrq_saveconfig: if ((daemonq == NULL) /* no more requests */ ||(daemonq->type != daemonrq_saveconfig)) { /* or the next isn't the same */ if (((daemon_options & daemon_noupdate) == 0) /* we're allowed to do it */ &&((vinum_conf.flags & VF_READING_CONFIG) == 0)) { /* and we're not building the config now */ /* * We obviously don't want to save a * partial configuration. Less obviously, * we don't need to do anything if we're * asked to write the config when we're * building it up, because we save it at * the end. */ if (daemon_options & daemon_verbose) log(LOG_INFO, "vinum: saving config\n"); daemon_save_config(); /* save it */ } } break; case daemonrq_return: /* been told to stop */ if (daemon_options & daemon_verbose) log(LOG_INFO, "vinum: stopping\n"); daemon_options |= daemon_stopped; /* note that we've stopped */ Free(request); while (daemonq != NULL) { /* backed up requests, */ request = daemonq; /* get the request */ daemonq = daemonq->next; /* and detach it */ Free(request); /* then free it */ } wakeup(&vinumclose); /* and wake any waiting vinum(8)s */ return; case daemonrq_ping: /* tell the caller we're here */ if (daemon_options & daemon_verbose) log(LOG_INFO, "vinum: ping reply\n"); wakeup(&vinum_finddaemon); /* wake up the caller */ break; case daemonrq_closedrive: /* close a drive */ close_drive(request->info.drive); /* do it */ break; case daemonrq_init: /* initialize a plex */ /* XXX */ case daemonrq_revive: /* revive a subdisk */ /* XXX */ /* FALLTHROUGH */ default: log(LOG_WARNING, "Invalid request\n"); break; } if (request->privateinuse) /* one of ours, */ request->privateinuse = 0; /* no longer in use */ else Free(request); /* return it */ } } }
/* Implement dir_lookup as described in <hurd/fs.defs>. */ kern_return_t diskfs_S_dir_lookup (struct protid *dircred, char *path, int flags, mode_t mode, enum retry_type *retry, char *retryname, file_t *returned_port, mach_msg_type_name_t *returned_port_poly) { struct node *dnp; struct node *np; int nsymlink = 0; char *nextname; char *relpath; int nextnamelen; error_t error = 0; char *pathbuf = 0; int pathbuflen = 0; int newnamelen; int create, excl; int lastcomp = 0; int newnode = 0; struct dirstat *ds = 0; int mustbedir = 0; size_t amt; int type; struct protid *newpi = 0; struct peropen *newpo = 0; if (!dircred) return EOPNOTSUPP; flags &= O_HURD; create = (flags & O_CREAT); excl = (flags & O_EXCL); /* Skip leading slashes */ while (path[0] == '/') path++; /* Preserve the path relative to diruser->po->path. */ relpath = strdup (path); if (! relpath) return ENOMEM; /* Keep a pointer to the start of the path for length calculations. */ char *path_start = path; *returned_port_poly = MACH_MSG_TYPE_MAKE_SEND; *retry = FS_RETRY_NORMAL; retryname[0] = '\0'; if (path[0] == '\0') { /* Set things up in the state expected by the code from gotit: on. */ dnp = 0; np = dircred->po->np; pthread_mutex_lock (&np->lock); diskfs_nref (np); goto gotit; } dnp = dircred->po->np; pthread_mutex_lock (&dnp->lock); np = 0; diskfs_nref (dnp); /* acquire a reference for later diskfs_nput */ do { assert (!lastcomp); /* Find the name of the next pathname component */ nextname = index (path, '/'); if (nextname) { *nextname++ = '\0'; while (*nextname == '/') nextname++; if (*nextname == '\0') { /* These are the rules for filenames ending in /. */ nextname = 0; lastcomp = 1; mustbedir = 1; create = 0; } else lastcomp = 0; } else lastcomp = 1; np = 0; /* diskfs_lookup the next pathname component */ if (lastcomp && create) { if (!ds) ds = alloca (diskfs_dirstat_size); error = diskfs_lookup (dnp, path, CREATE, &np, ds, dircred); } else error = diskfs_lookup (dnp, path, LOOKUP, &np, 0, dircred); if (lastcomp && create && excl && (!error || error == EAGAIN)) error = EEXIST; /* If we get an error we're done */ if (error == EAGAIN) { if (dnp == dircred->po->shadow_root) /* We're at the root of a shadow tree. */ { if (dircred->po->shadow_root_parent == MACH_PORT_NULL) { /* This is a shadow root with no parent, meaning we should treat it as a virtual root disconnected from its real .. directory. */ error = 0; np = dnp; diskfs_nref (np); } else { /* Punt the client up to the shadow root parent. */ *retry = FS_RETRY_REAUTH; *returned_port = dircred->po->shadow_root_parent; *returned_port_poly = MACH_MSG_TYPE_COPY_SEND; if (! lastcomp) strcpy (retryname, nextname); error = 0; goto out; } } else if (dircred->po->root_parent != MACH_PORT_NULL) /* We're at a real translator root; even if DIRCRED->po has a shadow root, we can get here if its in a directory that was renamed out from under it... */ { *retry = FS_RETRY_REAUTH; *returned_port = dircred->po->root_parent; *returned_port_poly = MACH_MSG_TYPE_COPY_SEND; if (!lastcomp) strcpy (retryname, nextname); error = 0; goto out; } else /* We're at a REAL root, as in there's no way up from here. */ { error = 0; np = dnp; diskfs_nref (np); } } /* Create the new node if necessary */ if (lastcomp && create) { if (error == ENOENT) { mode &= ~(S_IFMT | S_ISPARE | S_ISVTX | S_ITRANS); mode |= S_IFREG; error = diskfs_create_node (dnp, path, mode, &np, dircred, ds); if (diskfs_synchronous) { diskfs_file_update (dnp, 1); diskfs_file_update (np, 1); } newnode = 1; } else diskfs_drop_dirstat (dnp, ds); } if (error) goto out; /* If this is translated, start the translator (if necessary) and return. */ if ((((flags & O_NOTRANS) == 0) || !lastcomp) && ((np->dn_stat.st_mode & S_IPTRANS) || S_ISFIFO (np->dn_stat.st_mode) || S_ISCHR (np->dn_stat.st_mode) || S_ISBLK (np->dn_stat.st_mode) || fshelp_translated (&np->transbox))) { mach_port_t dirport; struct iouser *user; /* A callback function for short-circuited translators. Symlink & ifsock are handled elsewhere. */ error_t short_circuited_callback1 (void *cookie1, void *cookie2, uid_t *uid, gid_t *gid, char **argz, size_t *argz_len) { struct node *node = cookie1; switch (node->dn_stat.st_mode & S_IFMT) { case S_IFCHR: case S_IFBLK: asprintf (argz, "%s%c%d%c%d", (S_ISCHR (node->dn_stat.st_mode) ? _HURD_CHRDEV : _HURD_BLKDEV), 0, major (node->dn_stat.st_rdev), 0, minor (node->dn_stat.st_rdev)); *argz_len = strlen (*argz) + 1; *argz_len += strlen (*argz + *argz_len) + 1; *argz_len += strlen (*argz + *argz_len) + 1; break; case S_IFIFO: asprintf (argz, "%s", _HURD_FIFO); *argz_len = strlen (*argz) + 1; break; default: return ENOENT; } *uid = node->dn_stat.st_uid; *gid = node->dn_stat.st_gid; return 0; } /* Create an unauthenticated port for DNP, and then unlock it. */ error = iohelp_create_empty_iouser (&user); if (! error) { error = diskfs_make_peropen (dnp, 0, dircred->po, &newpo); if (! error) { error = diskfs_create_protid (newpo, user, &newpi); if (! error) newpo = 0; } iohelp_free_iouser (user); } if (error) goto out; dirport = ports_get_send_right (newpi); if (np != dnp) pthread_mutex_unlock (&dnp->lock); /* Check if an active translator is currently running. If not, fshelp_fetch_root will start one. In that case, we need to register it in the list of active translators. */ boolean_t register_translator = np->transbox.active == MACH_PORT_NULL; error = fshelp_fetch_root (&np->transbox, dircred->po, dirport, dircred->user, lastcomp ? flags : 0, ((np->dn_stat.st_mode & S_IPTRANS) ? _diskfs_translator_callback1 : short_circuited_callback1), _diskfs_translator_callback2, retry, retryname, returned_port); /* fetch_root copies DIRPORT for success, so we always should deallocate our send right. */ mach_port_deallocate (mach_task_self (), dirport); if (error != ENOENT) { *returned_port_poly = MACH_MSG_TYPE_MOVE_SEND; if (!lastcomp && !error) { char *end = strchr (retryname, '\0'); *end++ = '/'; strcpy (end, nextname); } if (register_translator) { char *translator_path = strdupa (relpath); char *complete_path; if (nextname != NULL) { /* This was not the last path component. NEXTNAME points to the next component, locate the end of the current component and use it to trim TRANSLATOR_PATH. */ char *end = nextname; while (*end != 0) end--; translator_path[end - path_start] = '\0'; } if (dircred->po->path == NULL || !strcmp (dircred->po->path,".")) /* dircred is the root directory. */ complete_path = translator_path; else asprintf (&complete_path, "%s/%s", dircred->po->path, translator_path); error = fshelp_set_active_translator (&newpi->pi, complete_path, np->transbox.active); if (complete_path != translator_path) free(complete_path); if (error) goto out; } goto out; } ports_port_deref (newpi); newpi = NULL; /* ENOENT means there was a hiccup, and the translator vanished while NP was unlocked inside fshelp_fetch_root. Reacquire the locks, and continue as normal. */ error = 0; if (np != dnp) { if (!strcmp (path, "..")) pthread_mutex_lock (&dnp->lock); else { if (pthread_mutex_trylock (&dnp->lock)) { pthread_mutex_unlock (&np->lock); pthread_mutex_lock (&dnp->lock); pthread_mutex_lock (&np->lock); } } } } if (S_ISLNK (np->dn_stat.st_mode) && (!lastcomp || mustbedir /* "foo/" must see that foo points to a dir */ || !(flags & (O_NOLINK|O_NOTRANS)))) { /* Handle symlink interpretation */ if (nsymlink++ > diskfs_maxsymlinks) { error = ELOOP; goto out; } nextnamelen = nextname ? strlen (nextname) + 1 : 0; newnamelen = nextnamelen + np->dn_stat.st_size + 1 + 1; if (pathbuflen < newnamelen) { pathbuf = alloca (newnamelen); pathbuflen = newnamelen; } if (diskfs_read_symlink_hook) error = (*diskfs_read_symlink_hook)(np, pathbuf); if (!diskfs_read_symlink_hook || error == EINVAL) { error = diskfs_node_rdwr (np, pathbuf, 0, np->dn_stat.st_size, 0, dircred, &amt); if (!error) assert (amt == np->dn_stat.st_size); } if (error) goto out; if (np->dn_stat.st_size == 0) /* symlink to "" */ path = nextname; else { if (nextname) { pathbuf[np->dn_stat.st_size] = '/'; memcpy (pathbuf + np->dn_stat.st_size + 1, nextname, nextnamelen - 1); } pathbuf[nextnamelen + np->dn_stat.st_size] = '\0'; if (pathbuf[0] == '/') { /* Punt to the caller. */ *retry = FS_RETRY_MAGICAL; *returned_port = MACH_PORT_NULL; memcpy (retryname, pathbuf, nextnamelen + np->dn_stat.st_size + 1); if (mustbedir) { retryname[nextnamelen + np->dn_stat.st_size] = '/'; retryname[nextnamelen + np->dn_stat.st_size + 1] = '\0'; } goto out; } path = pathbuf; } if (lastcomp) lastcomp = 0; diskfs_nput (np); np = 0; if (path == 0) /* symlink to "" was the last component */ { np = dnp; dnp = 0; break; } } else { /* Handle normal nodes */ path = nextname; if (np == dnp) diskfs_nrele (dnp); else diskfs_nput (dnp); if (!lastcomp) { dnp = np; np = 0; } else dnp = 0; } } while (path && *path);
static int enumerate_partitions(dev_t devnum) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; _cleanup_udev_device_unref_ struct udev_device *d = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_free_ char *boot = NULL, *home = NULL, *srv = NULL; struct udev_list_entry *first, *item; struct udev_device *parent = NULL; const char *name, *node, *pttype, *devtype; int boot_nr = -1, home_nr = -1, srv_nr = -1; bool home_rw = true, srv_rw = true; blkid_partlist pl; int r, k; dev_t pn; udev = udev_new(); if (!udev) return log_oom(); d = udev_device_new_from_devnum(udev, 'b', devnum); if (!d) return log_oom(); name = udev_device_get_devnode(d); if (!name) name = udev_device_get_syspath(d); if (!name) { log_debug("Device %u:%u does not have a name, ignoring.", major(devnum), minor(devnum)); return 0; } parent = udev_device_get_parent(d); if (!parent) { log_debug("%s: not a partitioned device, ignoring.", name); return 0; } /* Does it have a devtype? */ devtype = udev_device_get_devtype(parent); if (!devtype) { log_debug("%s: parent doesn't have a device type, ignoring.", name); return 0; } /* Is this a disk or a partition? We only care for disks... */ if (!streq(devtype, "disk")) { log_debug("%s: parent isn't a raw disk, ignoring.", name); return 0; } /* Does it have a device node? */ node = udev_device_get_devnode(parent); if (!node) { log_debug("%s: parent device does not have device node, ignoring.", name); return 0; } log_debug("%s: root device %s.", name, node); pn = udev_device_get_devnum(parent); if (major(pn) == 0) return 0; errno = 0; b = blkid_new_probe_from_filename(node); if (!b) { if (errno == 0) return log_oom(); return log_error_errno(errno, "%s: failed to allocate prober: %m", node); } blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == 1) return 0; /* no results */ else if (r == -2) { log_warning("%s: probe gave ambiguous results, ignoring", node); return 0; } else if (r != 0) return log_error_errno(errno ?: EIO, "%s: failed to probe: %m", node); errno = 0; r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL); if (r != 0) return log_error_errno(errno ?: EIO, "%s: failed to determine partition table type: %m", node); /* We only do this all for GPT... */ if (!streq_ptr(pttype, "gpt")) { log_debug("%s: not a GPT partition table, ignoring.", node); return 0; } errno = 0; pl = blkid_probe_get_partitions(b); if (!pl) { if (errno == 0) return log_oom(); return log_error_errno(errno, "%s: failed to list partitions: %m", node); } e = udev_enumerate_new(udev); if (!e) return log_oom(); r = udev_enumerate_add_match_parent(e, parent); if (r < 0) return log_oom(); r = udev_enumerate_add_match_subsystem(e, "block"); if (r < 0) return log_oom(); r = udev_enumerate_scan_devices(e); if (r < 0) return log_error_errno(r, "%s: failed to enumerate partitions: %m", node); first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *q; unsigned long long flags; const char *stype, *subnode; sd_id128_t type_id; blkid_partition pp; dev_t qn; int nr; q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!q) continue; qn = udev_device_get_devnum(q); if (major(qn) == 0) continue; if (qn == devnum) continue; if (qn == pn) continue; subnode = udev_device_get_devnode(q); if (!subnode) continue; pp = blkid_partlist_devno_to_partition(pl, qn); if (!pp) continue; nr = blkid_partition_get_partno(pp); if (nr < 0) continue; stype = blkid_partition_get_type_string(pp); if (!stype) continue; if (sd_id128_from_string(stype, &type_id) < 0) continue; flags = blkid_partition_get_flags(pp); if (sd_id128_equal(type_id, GPT_SWAP)) { if (flags & GPT_FLAG_NO_AUTO) continue; if (flags & GPT_FLAG_READ_ONLY) { log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode); continue; } k = add_swap(subnode); if (k < 0) r = k; } else if (sd_id128_equal(type_id, GPT_ESP)) { /* We only care for the first /boot partition */ if (boot && nr >= boot_nr) continue; /* Note that we do not honour the "no-auto" * flag for the ESP, as it is often unset, to * hide it from Windows. */ boot_nr = nr; r = free_and_strdup(&boot, subnode); if (r < 0) return log_oom(); } else if (sd_id128_equal(type_id, GPT_HOME)) { if (flags & GPT_FLAG_NO_AUTO) continue; /* We only care for the first /home partition */ if (home && nr >= home_nr) continue; home_nr = nr; home_rw = !(flags & GPT_FLAG_READ_ONLY), r = free_and_strdup(&home, subnode); if (r < 0) return log_oom(); } else if (sd_id128_equal(type_id, GPT_SRV)) { if (flags & GPT_FLAG_NO_AUTO) continue; /* We only care for the first /srv partition */ if (srv && nr >= srv_nr) continue; srv_nr = nr; srv_rw = !(flags & GPT_FLAG_READ_ONLY), r = free_and_strdup(&srv, subnode); if (r < 0) return log_oom(); } }
static int setup_tty(struct launcher_direct *launcher, int tty) { struct wl_event_loop *loop; struct vt_mode mode = { 0 }; struct stat buf; char tty_device[32] ="<stdin>"; int ret, kd_mode; if (tty == 0) { launcher->tty = dup(tty); if (launcher->tty == -1) { weston_log("couldn't dup stdin: %m\n"); return -1; } } else { snprintf(tty_device, sizeof tty_device, "/dev/tty%d", tty); launcher->tty = open(tty_device, O_RDWR | O_CLOEXEC); if (launcher->tty == -1) { weston_log("couldn't open tty %s: %m\n", tty_device); return -1; } } if (fstat(launcher->tty, &buf) == -1 || major(buf.st_rdev) != TTY_MAJOR || minor(buf.st_rdev) == 0) { weston_log("%s not a vt\n", tty_device); weston_log("if running weston from ssh, " "use --tty to specify a tty\n"); goto err_close; } ret = ioctl(launcher->tty, KDGETMODE, &kd_mode); if (ret) { weston_log("failed to get VT mode: %m\n"); return -1; } if (kd_mode != KD_TEXT) { weston_log("%s is already in graphics mode, " "is another display server running?\n", tty_device); goto err_close; } ioctl(launcher->tty, VT_ACTIVATE, minor(buf.st_rdev)); ioctl(launcher->tty, VT_WAITACTIVE, minor(buf.st_rdev)); if (ioctl(launcher->tty, KDGKBMODE, &launcher->kb_mode)) { weston_log("failed to read keyboard mode: %m\n"); goto err_close; } if (ioctl(launcher->tty, KDSKBMUTE, 1) && ioctl(launcher->tty, KDSKBMODE, K_OFF)) { weston_log("failed to set K_OFF keyboard mode: %m\n"); goto err_close; } ret = ioctl(launcher->tty, KDSETMODE, KD_GRAPHICS); if (ret) { weston_log("failed to set KD_GRAPHICS mode on tty: %m\n"); goto err_close; } /* * SIGRTMIN is used as global VT-acquire+release signal. Note that * SIGRT* must be tested on runtime, as their exact values are not * known at compile-time. POSIX requires 32 of them to be available. */ if (SIGRTMIN > SIGRTMAX) { weston_log("not enough RT signals available: %u-%u\n", SIGRTMIN, SIGRTMAX); ret = -EINVAL; goto err_close; } mode.mode = VT_PROCESS; mode.relsig = SIGRTMIN; mode.acqsig = SIGRTMIN; if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0) { weston_log("failed to take control of vt handling\n"); goto err_close; } loop = wl_display_get_event_loop(launcher->compositor->wl_display); launcher->vt_source = wl_event_loop_add_signal(loop, SIGRTMIN, vt_handler, launcher); if (!launcher->vt_source) goto err_close; return 0; err_close: close(launcher->tty); return -1; }
static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) { struct statfs sfs; struct stat st, st2; _cleanup_free_ char *t = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; int r; const char *v, *t2; if (statfs(p, &sfs) < 0) return log_error_errno(errno, "Failed to check file system type of \"%s\": %m", p); if (sfs.f_type != 0x4d44) { log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p); return -ENODEV; } if (stat(p, &st) < 0) return log_error_errno(errno, "Failed to determine block device node of \"%s\": %m", p); if (major(st.st_dev) == 0) { log_error("Block device node of %p is invalid.", p); return -ENODEV; } t2 = strjoina(p, "/.."); r = stat(t2, &st2); if (r < 0) return log_error_errno(errno, "Failed to determine block device node of parent of \"%s\": %m", p); if (st.st_dev == st2.st_dev) { log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p); return -ENODEV; } r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev)); if (r < 0) return log_oom(); errno = 0; b = blkid_new_probe_from_filename(t); if (!b) { if (errno == 0) return log_oom(); return log_error_errno(errno, "Failed to open file system \"%s\": %m", p); } blkid_probe_enable_superblocks(b, 1); blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE); blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == -2) { log_error("File system \"%s\" is ambiguous.", p); return -ENODEV; } else if (r == 1) { log_error("File system \"%s\" does not contain a label.", p); return -ENODEV; } else if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe file system \"%s\": %m", p); } errno = 0; r = blkid_probe_lookup_value(b, "TYPE", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe file system type \"%s\": %m", p); } if (!streq(v, "vfat")) { log_error("File system \"%s\" is not FAT.", p); return -ENODEV; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition scheme \"%s\": %m", p); } if (!streq(v, "gpt")) { log_error("File system \"%s\" is not on a GPT partition table.", p); return -ENODEV; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition type UUID \"%s\": %m", p); } if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) { log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p); return -ENODEV; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition entry UUID \"%s\": %m", p); } r = sd_id128_from_string(v, uuid); if (r < 0) { log_error("Partition \"%s\" has invalid UUID \"%s\".", p, v); return -EIO; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition number \"%s\": m", p); } *part = strtoul(v, NULL, 10); errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition offset \"%s\": %m", p); } *pstart = strtoul(v, NULL, 10); errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition size \"%s\": %m", p); } *psize = strtoul(v, NULL, 10); return 0; }
/*ARGSUSED*/ int mmrw(dev_t dev, struct uio *uio, int flags) { vaddr_t va; paddr_t pa; int o, c; struct iovec *iov; int error = 0; static int physlock; vm_prot_t prot; extern void *vmmap; if (minor(dev) == DEV_MEM) { /* lock against other uses of shared vmmap */ while (physlock > 0) { physlock++; error = tsleep((void *)&physlock, PZERO | PCATCH, "mmrw", 0); if (error) return (error); } physlock = 1; } while (uio->uio_resid > 0 && error == 0) { int n; iov = uio->uio_iov; if (iov->iov_len == 0) { uio->uio_iov++; uio->uio_iovcnt--; if (uio->uio_iovcnt < 0) panic("mmrw"); continue; } /* Note how much is still to go */ n = uio->uio_resid; switch (minor(dev)) { case DEV_MEM: pa = (paddr_t)uio->uio_offset; if (!pmap_pa_exists(pa)) { error = EFAULT; goto unlock; } prot = uio->uio_rw == UIO_READ ? VM_PROT_READ : VM_PROT_WRITE; pmap_enter(pmap_kernel(), (vaddr_t)vmmap, trunc_page(pa), prot, prot|PMAP_WIRED); pmap_update(pmap_kernel()); o = uio->uio_offset & PGOFSET; c = min(uio->uio_resid, (int)(PAGE_SIZE - o)); error = uiomove((char *)vmmap + o, c, uio); pmap_remove(pmap_kernel(), (vaddr_t)vmmap, (vaddr_t)vmmap + PAGE_SIZE); pmap_update(pmap_kernel()); break; case DEV_KMEM: va = (vaddr_t)uio->uio_offset; if (va >= MSGBUF_VA && va < MSGBUF_VA+PAGE_SIZE) { c = min(iov->iov_len, 4096); } else if (va >= prom_vstart && va < prom_vend && uio->uio_rw == UIO_READ) { /* Allow read-only access to the PROM */ c = min(iov->iov_len, prom_vend - prom_vstart); } else { c = min(iov->iov_len, MAXPHYS); if (!uvm_kernacc((void *)va, c, uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) return (EFAULT); } error = uiomove((void *)va, c, uio); break; case DEV_NULL: if (uio->uio_rw == UIO_WRITE) uio->uio_resid = 0; return (0); /* XXX should add sbus, etc */ #if defined(SUN4) case DEV_EEPROM: if (cputyp == CPU_SUN4) error = eeprom_uio(uio); else error = ENXIO; break; #endif /* SUN4 */ case DEV_ZERO: if (uio->uio_rw == UIO_WRITE) { uio->uio_resid = 0; return(0); } if (zeropage == NULL) { zeropage = (void *) malloc(PAGE_SIZE, M_TEMP, M_WAITOK); bzero(zeropage, PAGE_SIZE); } c = min(iov->iov_len, PAGE_SIZE); error = uiomove(zeropage, c, uio); break; default: return (ENXIO); } /* If we didn't make any progress (i.e. EOF), we're done here */ if (n == uio->uio_resid) break; } if (minor(dev) == 0) { unlock: if (physlock > 1) wakeup((void *)&physlock); physlock = 0; } return (error); }
/* read UMOCKDEV_SCRIPT_* environment variables and set up dev_logfile_map * according to it */ static void init_script_dev_logfile_map(void) { int i, dev; char varname[100]; const char *devname, *logname, *format; char *endptr; script_dev_logfile_map_inited = 1; for (i = 0; 1; ++i) { snprintf(varname, sizeof(varname), "UMOCKDEV_SCRIPT_RECORD_FILE_%i", i); logname = getenv(varname); if (logname == NULL) break; snprintf(varname, sizeof(varname), "UMOCKDEV_SCRIPT_RECORD_DEV_%i", i); devname = getenv(varname); if (devname == NULL) { fprintf(stderr, "umockdev: $%s not set\n", varname); exit(1); } snprintf(varname, sizeof(varname), "UMOCKDEV_SCRIPT_RECORD_FORMAT_%i", i); format = getenv(varname); if (format == NULL) { fprintf(stderr, "umockdev: $%s not set\n", varname); exit(1); } dev = strtol(devname, &endptr, 10); if (dev != 0 && *endptr == '\0') { /* if it's a number, then it is an rdev of a device */ /* ...and we should record its path */ const char *devpath; snprintf(varname, sizeof(varname), "UMOCKDEV_SCRIPT_RECORD_DEVICE_PATH_%i", i); devpath = getenv(varname); if (devpath == NULL) { fprintf(stderr, "umockdev: $%s not set\n", varname); exit(1); } DBG(DBG_SCRIPT, "init_script_dev_logfile_map: will record script of device %i:%i into %s\n", major(dev), minor(dev), logname); fd_map_add(&script_dev_logfile_map, dev, logname); fd_map_add(&script_dev_devpath_map, dev, devpath); if (strcmp(format, "default") == 0) fd_map_add(&script_dev_format_map, dev, (void*) FMT_DEFAULT); else if (strcmp(format, "evemu") == 0) fd_map_add(&script_dev_format_map, dev, (void*) FMT_EVEMU); else { fprintf(stderr, "umockdev: unknown device script record format '%s'\n", format); exit(1); } } else { if (strcmp(format, "default") != 0) { fprintf(stderr, "umockdev: unknown socket script record format '%s'\n", format); exit(1); } /* if it's a path, then we record a socket */ if (script_socket_logfile_len < MAX_SCRIPT_SOCKET_LOGFILE) { DBG(DBG_SCRIPT, "init_script_dev_logfile_map: will record script of socket %s into %s\n", devname, logname); script_socket_logfile[2*script_socket_logfile_len] = devname; script_socket_logfile[2*script_socket_logfile_len+1] = logname; script_socket_logfile_len++; } else { fprintf(stderr, "too many script sockets to record\n"); abort(); } } } }
/* * Call the low-level strategy routines to * perform the requests in a struct request */ int launch_requests(struct request *rq, int reviveok) { int s; struct rqgroup *rqg; int rqno; /* loop index */ struct rqelement *rqe; /* current element */ struct drive *drive; int rcount; /* request count */ /* * First find out whether we're reviving, and the * request contains a conflict. If so, we hang * the request off plex->waitlist of the first * plex we find which is reviving */ if ((rq->flags & XFR_REVIVECONFLICT) /* possible revive conflict */ &&(!reviveok)) { /* and we don't want to do it now, */ struct sd *sd; struct request *waitlist; /* point to the waitlist */ sd = &SD[rq->sdno]; if (sd->waitlist != NULL) { /* something there already, */ waitlist = sd->waitlist; while (waitlist->next != NULL) /* find the end */ waitlist = waitlist->next; waitlist->next = rq; /* hook our request there */ } else sd->waitlist = rq; /* hook our request at the front */ #if VINUMDEBUG if (debug & DEBUG_REVIVECONFLICT) log(LOG_DEBUG, "Revive conflict sd %d: %p\n%s dev %d.%d, offset 0x%x, length %ld\n", rq->sdno, rq, rq->bp->b_flags & B_READ ? "Read" : "Write", major(rq->bp->b_dev), minor(rq->bp->b_dev), rq->bp->b_blkno, rq->bp->b_bcount); #endif return 0; /* and get out of here */ } rq->active = 0; /* nothing yet */ #if VINUMDEBUG if (debug & DEBUG_ADDRESSES) log(LOG_DEBUG, "Request: %p\n%s dev %d.%d, offset 0x%x, length %ld\n", rq, rq->bp->b_flags & B_READ ? "Read" : "Write", major(rq->bp->b_dev), minor(rq->bp->b_dev), rq->bp->b_blkno, rq->bp->b_bcount); vinum_conf.lastrq = rq; vinum_conf.lastbuf = rq->bp; if (debug & DEBUG_LASTREQS) logrq(loginfo_user_bpl, (union rqinfou) rq->bp, rq->bp); #endif /* * With the division of labour below (first count the requests, then * issue them), it's possible that we don't need this splbio() * protection. But I'll try that some other time. */ s = splbio(); for (rqg = rq->rqg; rqg != NULL; rqg = rqg->next) { /* through the whole request chain */ rqg->active = rqg->count; /* they're all active */ for (rqno = 0; rqno < rqg->count; rqno++) { rqe = &rqg->rqe[rqno]; if (rqe->flags & XFR_BAD_SUBDISK) /* this subdisk is bad, */ rqg->active--; /* one less active request */ } if (rqg->active) /* we have at least one active request, */ rq->active++; /* one more active request group */ } /* Now fire off the requests */ for (rqg = rq->rqg; rqg != NULL;) { /* through the whole request chain */ if (rqg->lockbase >= 0) /* this rqg needs a lock first */ rqg->lock = lockrange(rqg->lockbase, rqg->rq->bp, &PLEX[rqg->plexno]); rcount = rqg->count; for (rqno = 0; rqno < rcount;) { rqe = &rqg->rqe[rqno]; /* * Point to next rqg before the bottom end * changes the structures. */ if (++rqno >= rcount) rqg = rqg->next; if ((rqe->flags & XFR_BAD_SUBDISK) == 0) { /* this subdisk is good, */ drive = &DRIVE[rqe->driveno]; /* look at drive */ drive->active++; if (drive->active >= drive->maxactive) drive->maxactive = drive->active; vinum_conf.active++; if (vinum_conf.active >= vinum_conf.maxactive) vinum_conf.maxactive = vinum_conf.active; #if VINUMDEBUG if (debug & DEBUG_ADDRESSES) log(LOG_DEBUG, " %s dev %d.%d, sd %d, offset 0x%x, devoffset 0x%x, length %ld\n", rqe->b.b_flags & B_READ ? "Read" : "Write", major(rqe->b.b_dev), minor(rqe->b.b_dev), rqe->sdno, (u_int) (rqe->b.b_blkno - SD[rqe->sdno].driveoffset), rqe->b.b_blkno, rqe->b.b_bcount); if (debug & DEBUG_LASTREQS) logrq(loginfo_rqe, (union rqinfou) rqe, rq->bp); #endif /* fire off the request */ BUF_STRATEGY(&rqe->b, 0); } } } splx(s); return 0; }
Errors Device_getDeviceInfo(DeviceInfo *deviceInfo, const String deviceName ) { FileStat fileStat; int handle; #if defined(HAVE_IOCTL) && defined(HAVE_BLKSSZGET) int i; #endif #if defined(HAVE_IOCTL) && defined(HAVE_BLKGETSIZE) long l; #endif FILE *mtab; struct mntent mountEntry; char buffer[4096]; assert(deviceName != NULL); assert(deviceInfo != NULL); // initialize variables deviceInfo->type = DEVICE_TYPE_UNKNOWN; deviceInfo->size = -1LL; deviceInfo->blockSize = 0L; // deviceInfo->freeBlocks = 0LL; // deviceInfo->totalBlocks = 0LL; deviceInfo->mountedFlag = FALSE; // get device meta data if (LSTAT(String_cString(deviceName),&fileStat) == 0) { deviceInfo->timeLastAccess = fileStat.st_atime; deviceInfo->timeModified = fileStat.st_mtime; deviceInfo->timeLastChanged = fileStat.st_ctime; deviceInfo->userId = fileStat.st_uid; deviceInfo->groupId = fileStat.st_gid; deviceInfo->permission = (DevicePermission)fileStat.st_mode; #ifdef HAVE_MAJOR deviceInfo->major = major(fileStat.st_rdev); #else deviceInfo->major = 0; #endif #ifdef HAVE_MINOR deviceInfo->minor = minor(fileStat.st_rdev); #else deviceInfo->minor = 0; #endif deviceInfo->id = (uint64)fileStat.st_ino; if (S_ISCHR(fileStat.st_mode)) deviceInfo->type = DEVICE_TYPE_CHARACTER; else if (S_ISBLK(fileStat.st_mode)) deviceInfo->type = DEVICE_TYPE_BLOCK; } if (deviceInfo->type == DEVICE_TYPE_BLOCK) { // try to get block size, total size handle = open(String_cString(deviceName),O_RDONLY); if (handle != -1) { #if defined(HAVE_IOCTL) && defined(HAVE_BLKSSZGET) if (ioctl(handle,BLKSSZGET, &i) == 0) deviceInfo->blockSize = (ulong)i; #endif #if defined(HAVE_IOCTL) && defined(HAVE_BLKGETSIZE) if (ioctl(handle,BLKGETSIZE,&l) == 0) deviceInfo->size = (int64)l*512; #endif close(handle); } } // check if mounted mtab = setmntent("/etc/mtab","r"); if (mtab != NULL) { while (getmntent_r(mtab,&mountEntry,buffer,sizeof(buffer)) != NULL) { if (String_equalsCString(deviceName,mountEntry.mnt_fsname)) { deviceInfo->mountedFlag = TRUE; break; } } endmntent(mtab); } return ERROR_NONE; }
/* Perform I/O on a subdisk */ void sdio(struct buf *bp) { int s; /* spl */ struct sd *sd; struct sdbuf *sbp; daddr_t endoffset; struct drive *drive; #if VINUMDEBUG if (debug & DEBUG_LASTREQS) logrq(loginfo_sdio, (union rqinfou) bp, bp); #endif sd = &SD[Sdno(bp->b_dev)]; /* point to the subdisk */ drive = &DRIVE[sd->driveno]; if (drive->state != drive_up) { if (sd->state >= sd_crashed) { if (bp->b_flags & B_READ) /* reading, */ set_sd_state(sd->sdno, sd_crashed, setstate_force); else set_sd_state(sd->sdno, sd_stale, setstate_force); } bp->b_flags |= B_ERROR; bp->b_error = EIO; biodone(bp); return; } /* * We allow access to any kind of subdisk as long as we can expect * to get the I/O performed. */ if (sd->state < sd_empty) { /* nothing to talk to, */ bp->b_flags |= B_ERROR; bp->b_error = EIO; biodone(bp); return; } /* Get a buffer */ sbp = (struct sdbuf *) Malloc(sizeof(struct sdbuf)); if (sbp == NULL) { bp->b_flags |= B_ERROR; bp->b_error = ENOMEM; biodone(bp); return; } bzero(sbp, sizeof(struct sdbuf)); /* start with nothing */ sbp->b.b_flags = bp->b_flags | B_CALL; /* inform us when it's done */ sbp->b.b_bufsize = bp->b_bufsize; /* buffer size */ sbp->b.b_bcount = bp->b_bcount; /* number of bytes to transfer */ sbp->b.b_resid = bp->b_resid; /* and amount waiting */ sbp->b.b_dev = DRIVE[sd->driveno].dev; /* device */ sbp->b.b_data = bp->b_data; /* data buffer */ sbp->b.b_blkno = bp->b_blkno + sd->driveoffset; sbp->b.b_iodone = sdio_done; /* come here on completion */ BUF_LOCKINIT(&sbp->b); /* get a lock for the buffer */ BUF_LOCK(&sbp->b, LK_EXCLUSIVE); /* and lock it */ sbp->bp = bp; /* note the address of the original header */ sbp->sdno = sd->sdno; /* note for statistics */ sbp->driveno = sd->driveno; endoffset = bp->b_blkno + sbp->b.b_bcount / DEV_BSIZE; /* final sector offset */ if (endoffset > sd->sectors) { /* beyond the end */ sbp->b.b_bcount -= (endoffset - sd->sectors) * DEV_BSIZE; /* trim */ if (sbp->b.b_bcount <= 0) { /* nothing to transfer */ bp->b_resid = bp->b_bcount; /* nothing transferred */ biodone(bp); Free(sbp); return; } } #if VINUMDEBUG if (debug & DEBUG_ADDRESSES) log(LOG_DEBUG, " %s dev %d.%d, sd %d, offset 0x%x, devoffset 0x%x, length %ld\n", sbp->b.b_flags & B_READ ? "Read" : "Write", major(sbp->b.b_dev), minor(sbp->b.b_dev), sbp->sdno, (u_int) (sbp->b.b_blkno - SD[sbp->sdno].driveoffset), (int) sbp->b.b_blkno, sbp->b.b_bcount); #endif s = splbio(); #if VINUMDEBUG if (debug & DEBUG_LASTREQS) logrq(loginfo_sdiol, (union rqinfou) &sbp->b, &sbp->b); #endif BUF_STRATEGY(&sbp->b, 0); splx(s); }
int cdread(uint16_t dev, uint8_t flag) { validchk(dev, PANIC_CDR); return ((*dev_tab[major(dev)].dev_read) (minor(dev), 1, flag)); }
int mmc_is_path_at_device_offset(const char *file_path, off_t block_offset) { struct stat file_st; if (stat(file_path, &file_st) < 0) return -1; // Now check that the offset is in the right place by reading the sysfs file. char start_path[64]; snprintf(start_path, sizeof(start_path), "/sys/dev/block/%d:%d/start", major(file_st.st_dev), minor(file_st.st_dev)); char start[16]; if (readsysfs(start_path, start, sizeof(start)) <= 0) return -1; off_t start_offset = strtoull(start, NULL, 0); return start_offset == block_offset ? 1 : 0; }