void decode_ss(const char *arg) { struct sockaddr_storage *ssp; size_t len = strlen(arg); if (len > sizeof(*ssp) * 4 + 1 || len < sizeof(*ssp)) errx(EXIT_FAILURE, "Bad argument"); if ((ssp = malloc(len)) == NULL) err(EXIT_FAILURE, NULL); if (strunvis((char *)ssp, arg) != sizeof(*ssp)) errx(EXIT_FAILURE, "Decoding error"); (void)memcpy(&ss, ssp, sizeof(ss)); free(ssp); have_ss = 1; }
ATF_TC_BODY(strunvis_hex, tc) { static const struct { const char *e; const char *d; int error; } ed[] = { { "\\xff", "\xff", 1 }, { "\\x1", "\x1", 1 }, { "\\x1\\x02", "\x1\x2", 2 }, { "\\x1x", "\x1x", 2 }, { "\\xx", "", -1 }, }; char uv[10]; for (size_t i = 0; i < __arraycount(ed); i++) { ATF_REQUIRE(strunvis(uv, ed[i].e) == ed[i].error); if (ed[i].error > 0) ATF_REQUIRE(memcmp(ed[i].d, uv, ed[i].error) == 0); } }
NODE * spec(FILE *fp) { NODE *centry, *last, *pathparent, *cur; char *p, *e, *next; NODE ginfo, *root; char *buf, *tname, *ntname; size_t tnamelen, plen; root = NULL; centry = last = NULL; tname = NULL; tnamelen = 0; memset(&ginfo, 0, sizeof(ginfo)); for (mtree_lineno = 0; (buf = fparseln(fp, NULL, &mtree_lineno, NULL, FPARSELN_UNESCCOMM)); free(buf)) { /* Skip leading whitespace. */ for (p = buf; *p && isspace((unsigned char)*p); ++p) continue; /* If nothing but whitespace, continue. */ if (!*p) continue; #ifdef DEBUG fprintf(stderr, "line %lu: {%s}\n", (u_long)mtree_lineno, p); #endif /* Grab file name, "$", "set", or "unset". */ next = buf; while ((p = strsep(&next, " \t")) != NULL && *p == '\0') continue; if (p == NULL) mtree_err("missing field"); if (p[0] == '/') { if (strcmp(p + 1, "set") == 0) set(next, &ginfo); else if (strcmp(p + 1, "unset") == 0) unset(next, &ginfo); else mtree_err("invalid specification `%s'", p); continue; } if (strcmp(p, "..") == 0) { /* Don't go up, if haven't gone down. */ if (root == NULL) goto noparent; if (last->type != F_DIR || last->flags & F_DONE) { if (last == root) goto noparent; last = last->parent; } last->flags |= F_DONE; continue; noparent: mtree_err("no parent node"); } plen = strlen(p) + 1; if (plen > tnamelen) { if ((ntname = realloc(tname, plen)) == NULL) mtree_err("realloc: %s", strerror(errno)); tname = ntname; tnamelen = plen; } if (strunvis(tname, p) == -1) mtree_err("strunvis failed on `%s'", p); p = tname; pathparent = NULL; if (strchr(p, '/') != NULL) { cur = root; for (; (e = strchr(p, '/')) != NULL; p = e+1) { if (p == e) continue; /* handle // */ *e = '\0'; if (strcmp(p, ".") != 0) { while (cur && strcmp(cur->name, p) != 0) { cur = cur->next; } } if (cur == NULL || cur->type != F_DIR) { mtree_err("%s: %s", tname, "missing directory in specification"); } *e = '/'; pathparent = cur; cur = cur->child; } if (*p == '\0') mtree_err("%s: empty leaf element", tname); } if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL) mtree_err("%s", strerror(errno)); *centry = ginfo; centry->lineno = mtree_lineno; strcpy(centry->name, p); #define MAGIC "?*[" if (strpbrk(p, MAGIC)) centry->flags |= F_MAGIC; set(next, centry); if (root == NULL) { /* * empty tree */ if (strcmp(centry->name, ".") != 0 || centry->type != F_DIR) mtree_err( "root node must be the directory `.'"); last = root = centry; root->parent = root; } else if (pathparent != NULL) { /* * full path entry; add or replace */ centry->parent = pathparent; addchild(pathparent, centry); last = centry; } else if (strcmp(centry->name, ".") == 0) { /* * duplicate "." entry; always replace */ replacenode(root, centry); } else if (last->type == F_DIR && !(last->flags & F_DONE)) { /* * new relative child in current dir; * add or replace */ centry->parent = last; addchild(last, centry); last = centry; } else { /* * new relative child in parent dir * (after encountering ".." entry); * add or replace */ centry->parent = last->parent; addchild(last->parent, centry); last = centry; } } return (root); }
NODE * spec(void) { NODE *centry, *last; char *p; NODE ginfo, *root; int c_cur, c_next; char buf[2048]; centry = last = root = NULL; bzero(&ginfo, sizeof(ginfo)); c_cur = c_next = 0; for (lineno = 1; fgets(buf, sizeof(buf), stdin); ++lineno, c_cur = c_next, c_next = 0) { /* Skip empty lines. */ if (buf[0] == '\n') continue; /* Find end of line. */ if ((p = strchr(buf, '\n')) == NULL) errx(1, "line %d too long", lineno); /* See if next line is continuation line. */ if (p[-1] == '\\') { --p; c_next = 1; } /* Null-terminate the line. */ *p = '\0'; /* Skip leading whitespace. */ for (p = buf; *p && isspace(*p); ++p); /* If nothing but whitespace or comment char, continue. */ if (!*p || *p == '#') continue; #ifdef DEBUG fprintf(stderr, "line %d: {%s}\n", lineno, p); #endif if (c_cur) { set(p, centry); continue; } /* Grab file name, "$", "set", or "unset". */ if ((p = strtok(p, "\n\t ")) == NULL) errx(1, "line %d: missing field", lineno); if (p[0] == '/') switch(p[1]) { case 's': if (strcmp(p + 1, "set")) break; set(NULL, &ginfo); continue; case 'u': if (strcmp(p + 1, "unset")) break; unset(NULL, &ginfo); continue; } if (strchr(p, '/')) errx(1, "line %d: slash character in file name", lineno); if (!strcmp(p, "..")) { /* Don't go up, if haven't gone down. */ if (!root) goto noparent; if (last->type != F_DIR || last->flags & F_DONE) { if (last == root) goto noparent; last = last->parent; } last->flags |= F_DONE; continue; noparent: errx(1, "line %d: no parent node", lineno); } if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL) errx(1, "calloc"); *centry = ginfo; #define MAGIC "?*[" if (strpbrk(p, MAGIC)) centry->flags |= F_MAGIC; if (strunvis(centry->name, p) == -1) { warnx("filename %s is ill-encoded and literally used", p); strcpy(centry->name, p); } set(NULL, centry); if (!root) { last = root = centry; root->parent = root; } else if (last->type == F_DIR && !(last->flags & F_DONE)) { centry->parent = last; last = last->child = centry; } else { centry->parent = last->parent; centry->prev = last; last = last->next = centry; } } return (root); }
static int fstabscan(void) { char *cp, *p; #define MAXLINELENGTH 1024 static char line[MAXLINELENGTH]; char subline[MAXLINELENGTH]; int typexx; for (;;) { if (!(p = fgets(line, sizeof(line), _fs_fp))) return (0); /* OLD_STYLE_FSTAB */ ++LineNo; if (*line == '#' || *line == '\n') continue; if (!strpbrk(p, " \t")) { _fs_fstab.fs_spec = strsep(&p, ":\n"); _fs_fstab.fs_file = strsep(&p, ":\n"); fixfsfile(); _fs_fstab.fs_type = strsep(&p, ":\n"); if (_fs_fstab.fs_type) { if (!strcmp(_fs_fstab.fs_type, FSTAB_XX)) continue; _fs_fstab.fs_mntops = _fs_fstab.fs_type; _fs_fstab.fs_vfstype = strcmp(_fs_fstab.fs_type, FSTAB_SW) ? "ufs" : "swap"; if ((cp = strsep(&p, ":\n")) != NULL) { _fs_fstab.fs_freq = atoi(cp); if ((cp = strsep(&p, ":\n")) != NULL) { _fs_fstab.fs_passno = atoi(cp); return (1); } } } goto bad; } /* OLD_STYLE_FSTAB */ while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0') ; _fs_fstab.fs_spec = cp; if (_fs_fstab.fs_spec == NULL || *_fs_fstab.fs_spec == '#') continue; if (strunvis(_fs_fstab.fs_spec, _fs_fstab.fs_spec) < 0) goto bad; while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0') ; _fs_fstab.fs_file = cp; if (_fs_fstab.fs_file == NULL) goto bad; if (strunvis(_fs_fstab.fs_file, _fs_fstab.fs_file) < 0) goto bad; fixfsfile(); while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0') ; _fs_fstab.fs_vfstype = cp; while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0') ; _fs_fstab.fs_mntops = cp; if (_fs_fstab.fs_mntops == NULL) goto bad; _fs_fstab.fs_freq = 0; _fs_fstab.fs_passno = 0; while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0') ; if (cp != NULL) { _fs_fstab.fs_freq = atoi(cp); while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0') ; if (cp != NULL) _fs_fstab.fs_passno = atoi(cp); } (void)strlcpy(subline, _fs_fstab.fs_mntops, sizeof(subline)); p = subline; for (typexx = 0, cp = strsep(&p, ","); cp; cp = strsep(&p, ",")) { if (strlen(cp) != 2) continue; if (!strcmp(cp, FSTAB_RW)) { _fs_fstab.fs_type = FSTAB_RW; break; } if (!strcmp(cp, FSTAB_RQ)) { _fs_fstab.fs_type = FSTAB_RQ; break; } if (!strcmp(cp, FSTAB_RO)) { _fs_fstab.fs_type = FSTAB_RO; break; } if (!strcmp(cp, FSTAB_SW)) { _fs_fstab.fs_type = FSTAB_SW; break; } if (!strcmp(cp, FSTAB_XX)) { _fs_fstab.fs_type = FSTAB_XX; typexx++; break; } } if (typexx) continue; if (cp != NULL) return (1); bad: /* no way to distinguish between EOF and syntax error */ error(EFTYPE); } /* NOTREACHED */ }
NODE * spec(void) { NODE *centry, *last; char *p; NODE ginfo, *root; int c_cur, c_next; char *buf, *tbuf = NULL; size_t len; last = root = NULL; bzero(&ginfo, sizeof(ginfo)); centry = &ginfo; c_cur = c_next = 0; for (lineno = 1; (buf = fgetln(stdin, &len)); ++lineno, c_cur = c_next, c_next = 0) { /* Null-terminate the line. */ if (buf[len - 1] == '\n') { buf[--len] = '\0'; } else { /* EOF with no newline. */ tbuf = malloc(len + 1); memcpy(tbuf, buf, len); tbuf[len] = '\0'; buf = tbuf; } /* Skip leading whitespace. */ for (p = buf; isspace((unsigned char)*p); p++) ; /* If nothing but whitespace or comment char, continue. */ if (*p == '\0' || *p == '#') continue; /* See if next line is continuation line. */ if (buf[len - 1] == '\\') { c_next = 1; if (--len == 0) continue; buf[len] = '\0'; } #ifdef DEBUG (void)fprintf(stderr, "line %d: {%s}\n", lineno, p); #endif if (c_cur) { set(p, centry); continue; } /* Grab file name, "$", "set", or "unset". */ if ((p = strtok(p, "\n\t ")) == NULL) error("missing field"); if (p[0] == '/') switch(p[1]) { case 's': if (strcmp(p + 1, "set")) break; set(NULL, &ginfo); continue; case 'u': if (strcmp(p + 1, "unset")) break; unset(NULL, &ginfo); continue; } if (strchr(p, '/')) error("slash character in file name"); if (!strcmp(p, "..")) { /* Don't go up, if haven't gone down. */ if (!root) goto noparent; if (last->type != F_DIR || last->flags & F_DONE) { if (last == root) goto noparent; last = last->parent; } last->flags |= F_DONE; continue; noparent: error("no parent node"); } len = strlen(p) + 1; /* NUL in struct _node */ if ((centry = calloc(1, sizeof(NODE) + len - 1)) == NULL) error("%s", strerror(errno)); *centry = ginfo; #define MAGIC "?*[" if (strpbrk(p, MAGIC)) centry->flags |= F_MAGIC; if (strunvis(centry->name, p) == -1) { fprintf(stderr, "mtree: filename (%s) encoded incorrectly\n", p); strlcpy(centry->name, p, len); } set(NULL, centry); if (!root) { last = root = centry; root->parent = root; } else if (last->type == F_DIR && !(last->flags & F_DONE)) { centry->parent = last; last = last->child = centry; } else { centry->parent = last->parent; centry->prev = last; last = last->next = centry; } } free(tbuf); return (root); }
static void set(char *t, NODE *ip) { int type; char *kw, *val = NULL; struct group *gr; struct passwd *pw; void *m; int value; u_int32_t fset, fclr; char *ep; size_t len; for (; (kw = strtok(t, "= \t\n")); t = NULL) { ip->flags |= type = parsekey(kw, &value); if (value && (val = strtok(NULL, " \t\n")) == NULL) error("missing value"); switch(type) { case F_CKSUM: ip->cksum = strtoul(val, &ep, 10); if (*ep) error("invalid checksum %s", val); break; case F_MD5: ip->md5digest = strdup(val); if (!ip->md5digest) error("%s", strerror(errno)); break; case F_FLAGS: if (!strcmp(val, "none")) { ip->file_flags = 0; break; } if (strtofflags(&val, &fset, &fclr)) error("%s", strerror(errno)); ip->file_flags = fset; break; case F_GID: ip->st_gid = strtoul(val, &ep, 10); if (*ep) error("invalid gid %s", val); break; case F_GNAME: if ((gr = getgrnam(val)) == NULL) error("unknown group %s", val); ip->st_gid = gr->gr_gid; break; case F_IGN: /* just set flag bit */ break; case F_MODE: if ((m = setmode(val)) == NULL) error("invalid file mode %s", val); ip->st_mode = getmode(m, 0); free(m); break; case F_NLINK: ip->st_nlink = strtoul(val, &ep, 10); if (*ep) error("invalid link count %s", val); break; case F_RMD160: ip->rmd160digest = strdup(val); if (!ip->rmd160digest) error("%s", strerror(errno)); break; case F_SHA1: ip->sha1digest = strdup(val); if (!ip->sha1digest) error("%s", strerror(errno)); break; case F_SIZE: ip->st_size = strtouq(val, &ep, 10); if (*ep) error("invalid size %s", val); break; case F_SLINK: len = strlen(val) + 1; if ((ip->slink = malloc(len)) == NULL) error("%s", strerror(errno)); if (strunvis(ip->slink, val) == -1) { fprintf(stderr, "mtree: filename (%s) encoded incorrectly\n", val); strlcpy(ip->slink, val, len); } break; case F_TIME: ip->st_mtimespec.tv_sec = strtoul(val, &ep, 10); if (*ep != '.') error("invalid time %s", val); val = ep + 1; ip->st_mtimespec.tv_nsec = strtoul(val, &ep, 10); if (*ep) error("invalid time %s", val); break; case F_TYPE: switch(*val) { case 'b': if (!strcmp(val, "block")) ip->type = F_BLOCK; break; case 'c': if (!strcmp(val, "char")) ip->type = F_CHAR; break; case 'd': if (!strcmp(val, "dir")) ip->type = F_DIR; break; case 'f': if (!strcmp(val, "file")) ip->type = F_FILE; if (!strcmp(val, "fifo")) ip->type = F_FIFO; break; case 'l': if (!strcmp(val, "link")) ip->type = F_LINK; break; case 's': if (!strcmp(val, "socket")) ip->type = F_SOCK; break; default: error("unknown file type %s", val); } break; case F_UID: ip->st_uid = strtoul(val, &ep, 10); if (*ep) error("invalid uid %s", val); break; case F_UNAME: if ((pw = getpwnam(val)) == NULL) error("unknown user %s", val); ip->st_uid = pw->pw_uid; break; } } }
const char * getfsspecname(char *buf, size_t bufsiz, const char *name) { static const int mib[] = { CTL_HW, HW_DISKNAMES }; static const unsigned int miblen = __arraycount(mib); char *drives, *dk; size_t len; int fd, savee; char *vname; drives = NULL; vname = NULL; if (strncasecmp(name, "NAME=", 5) != 0) { #ifdef COMPAT_DKWEDGE /* * We try to open the disk name, and if we fail with EBUSY * we use the name as the label to find the wedge. */ char rbuf[MAXPATHLEN]; if (name[0] == '/') { if (getdiskrawname(rbuf, sizeof(rbuf), name) != NULL) { if ((fd = open(rbuf, O_RDONLY)) == -1) { if (errno == EBUSY) { name = strrchr(name, '/') + 1; goto search; } } else close(fd); } } #endif strlcpy(buf, name, bufsiz); return buf; } else name += 5; #ifdef COMPAT_DKWEDGE search: #endif vname = malloc(strlen(name) * 4 + 1); if (vname == NULL) { savee = errno; strlcpy(buf, "malloc failed", bufsiz); goto out; } strunvis(vname, name); if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) { savee = errno; strlcpy(buf, "sysctl hw.disknames failed", bufsiz); goto out; } drives = malloc(len); if (drives == NULL) { savee = errno; strlcpy(buf, "malloc failed", bufsiz); goto out; } if (sysctl(mib, miblen, drives, &len, NULL, 0) == -1) { savee = errno; strlcpy(buf, "sysctl hw.disknames failed", bufsiz); goto out; } for (dk = strtok(drives, " "); dk != NULL; dk = strtok(NULL, " ")) { struct dkwedge_info dkw; if (strncmp(dk, "dk", 2) != 0) continue; fd = opendisk(dk, O_RDONLY, buf, bufsiz, 0); if (fd == -1) continue; if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == -1) { savee = errno; snprintf(buf, bufsiz, "%s: getwedgeinfo", dk); (void)close(fd); goto out; } (void)close(fd); if (strcmp(vname, (char *)dkw.dkw_wname) == 0) { char *p = strstr(buf, "/rdk"); if (p++ == NULL) return buf; strcpy(p, p + 1); free(drives); free(vname); return buf; } } savee = ESRCH; snprintf(buf, bufsiz, "no match for `%s'", vname); out: free(drives); free(vname); errno = savee; return NULL; }