spec.c revision 1.63
1139825Simp/* $NetBSD: spec.c,v 1.63 2006/10/08 18:09:47 martin Exp $ */ 240711Swollman 340711Swollman/*- 440711Swollman * Copyright (c) 1989, 1993 540711Swollman * The Regents of the University of California. All rights reserved. 640711Swollman * 740711Swollman * Redistribution and use in source and binary forms, with or without 840711Swollman * modification, are permitted provided that the following conditions 940711Swollman * are met: 1040711Swollman * 1. Redistributions of source code must retain the above copyright 1140711Swollman * notice, this list of conditions and the following disclaimer. 1240711Swollman * 2. Redistributions in binary form must reproduce the above copyright 1340711Swollman * notice, this list of conditions and the following disclaimer in the 1440711Swollman * documentation and/or other materials provided with the distribution. 1540711Swollman * 3. Neither the name of the University nor the names of its contributors 1640711Swollman * may be used to endorse or promote products derived from this software 1740711Swollman * without specific prior written permission. 1840711Swollman * 1940711Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2040711Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2140711Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2240711Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2340711Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2440711Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2540711Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2640711Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2740711Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2840711Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2950477Speter * SUCH DAMAGE. 3040711Swollman */ 3140711Swollman 3240711Swollman/*- 3340711Swollman * Copyright (c) 2001-2004 The NetBSD Foundation, Inc. 3440711Swollman * All rights reserved. 3555205Speter * 3640711Swollman * This code is derived from software contributed to The NetBSD Foundation 37129887Simp * by Luke Mewburn of Wasabi Systems. 38129887Simp * 39129887Simp * Redistribution and use in source and binary forms, with or without 4055205Speter * modification, are permitted provided that the following conditions 4140711Swollman * are met: 4268522Smsmith * 1. Redistributions of source code must retain the above copyright 4368522Smsmith * notice, this list of conditions and the following disclaimer. 4468522Smsmith * 2. Redistributions in binary form must reproduce the above copyright 4568522Smsmith * notice, this list of conditions and the following disclaimer in the 4668522Smsmith * documentation and/or other materials provided with the distribution. 4768522Smsmith * 3. All advertising materials mentioning features or use of this software 4882378Sjon * must display the following acknowledgement: 49150521Sphk * This product includes software developed by the NetBSD 5068522Smsmith * Foundation, Inc. and its contributors. 5168522Smsmith * 4. Neither the name of The NetBSD Foundation nor the names of its 5268522Smsmith * contributors may be used to endorse or promote products derived 5368522Smsmith * from this software without specific prior written permission. 5468522Smsmith * 5568522Smsmith * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 5668522Smsmith * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 5768522Smsmith * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 5868522Smsmith * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 5940711Swollman * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6068522Smsmith * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 6168522Smsmith * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 6268522Smsmith * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 6368522Smsmith * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 6468522Smsmith * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 6568522Smsmith * POSSIBILITY OF SUCH DAMAGE. 6668522Smsmith */ 6768522Smsmith 6868522Smsmith#if HAVE_NBTOOL_CONFIG_H 6968522Smsmith#include "nbtool_config.h" 7068522Smsmith#endif 7168522Smsmith 7268522Smsmith#include <sys/cdefs.h> 7368522Smsmith#if defined(__RCSID) && !defined(lint) 7468522Smsmith#if 0 7568522Smsmithstatic char sccsid[] = "@(#)spec.c 8.2 (Berkeley) 4/28/95"; 7668522Smsmith#else 7768522Smsmith__RCSID("$NetBSD: spec.c,v 1.63 2006/10/08 18:09:47 martin Exp $"); 7868522Smsmith#endif 7968522Smsmith#endif /* not lint */ 8068522Smsmith 8168522Smsmith#include <sys/param.h> 8268522Smsmith#include <sys/stat.h> 8368522Smsmith 8468522Smsmith#include <ctype.h> 8568522Smsmith#include <errno.h> 8668522Smsmith#include <grp.h> 8768522Smsmith#include <pwd.h> 88150523Sphk#include <stdio.h> 8968522Smsmith#include <stdlib.h> 90150523Sphk#include <string.h> 91150523Sphk#include <unistd.h> 92150523Sphk#include <vis.h> 93150523Sphk#include <util.h> 94150523Sphk 95150523Sphk#include "extern.h" 96150523Sphk#include "pack_dev.h" 97150523Sphk 98150523Sphksize_t mtree_lineno; /* Current spec line number */ 99150523Sphkint mtree_Mflag; /* Merge duplicate entries */ 100150523Sphkint mtree_Wflag; /* Don't "whack" permissions */ 101150523Sphk 102150523Sphkstatic dev_t parsedev(char *); 103150523Sphkstatic void replacenode(NODE *, NODE *); 10440711Swollmanstatic void set(char *, NODE *); 10540711Swollmanstatic void unset(char *, NODE *); 10640711Swollman 10768527Swollman#define REPLACEPTR(x,v) do { if ((x)) free((x)); (x) = (v); } while (0) 10868527Swollman 10968527SwollmanNODE * 11068527Swollmanspec(FILE *fp) 11140711Swollman{ 112150523Sphk NODE *centry, *last, *pathparent, *cur; 113131344Simp char *p, *e, *next; 114150523Sphk NODE ginfo, *root; 115150523Sphk char *buf, *tname, *ntname; 116150523Sphk size_t tnamelen, plen; 117150523Sphk 118150523Sphk root = NULL; 11940711Swollman centry = last = NULL; 12040711Swollman tname = NULL; 12140711Swollman tnamelen = 0; 12240711Swollman memset(&ginfo, 0, sizeof(ginfo)); 12340711Swollman for (mtree_lineno = 0; 12440711Swollman (buf = fparseln(fp, NULL, &mtree_lineno, NULL, 125135068Simp FPARSELN_UNESCCOMM)); 126135068Simp free(buf)) { 127107296Simp /* Skip leading whitespace. */ 12840711Swollman for (p = buf; *p && isspace((unsigned char)*p); ++p) 129131413Simp continue; 130131413Simp 131131413Simp /* If nothing but whitespace, continue. */ 13240711Swollman if (!*p) 13383045Sobrien continue; 13440711Swollman 13571576Sjasone#ifdef DEBUG 13660938Sjake fprintf(stderr, "line %lu: {%s}\n", 13740711Swollman (u_long)mtree_lineno, p); 13840711Swollman#endif 13940711Swollman /* Grab file name, "$", "set", or "unset". */ 14040711Swollman next = buf; 14140711Swollman while ((p = strsep(&next, " \t")) != NULL && *p == '\0') 14260938Sjake continue; 14340711Swollman if (p == NULL) 14440711Swollman mtree_err("missing field"); 14540711Swollman 146137492Simp if (p[0] == '/') { 147137492Simp if (strcmp(p + 1, "set") == 0) 148137492Simp set(next, &ginfo); 149137492Simp else if (strcmp(p + 1, "unset") == 0) 150137492Simp unset(next, &ginfo); 151137492Simp else 152137492Simp mtree_err("invalid specification `%s'", p); 153137492Simp continue; 154137492Simp } 15540711Swollman 15640711Swollman if (strcmp(p, "..") == 0) { 15740711Swollman /* Don't go up, if haven't gone down. */ 158137492Simp if (root == NULL) 15940711Swollman goto noparent; 16040711Swollman if (last->type != F_DIR || last->flags & F_DONE) { 16183045Sobrien if (last == root) 16240711Swollman goto noparent; 16340711Swollman last = last->parent; 16488372Stmm } 16588372Stmm last->flags |= F_DONE; 16688372Stmm continue; 167137496Simp 168107296Simpnoparent: mtree_err("no parent node"); 169144932Simp } 170137492Simp 171107296Simp plen = strlen(p) + 1; 172131413Simp if (plen > tnamelen) { 173137492Simp if ((ntname = realloc(tname, plen)) == NULL) 17440711Swollman mtree_err("realloc: %s", strerror(errno)); 17540711Swollman tname = ntname; 17655205Speter tnamelen = plen; 17740711Swollman } 17840711Swollman if (strunvis(tname, p) == -1) 179 mtree_err("strunvis failed on `%s'", p); 180 p = tname; 181 182 pathparent = NULL; 183 if (strchr(p, '/') != NULL) { 184 cur = root; 185 for (; (e = strchr(p, '/')) != NULL; p = e+1) { 186 if (p == e) 187 continue; /* handle // */ 188 *e = '\0'; 189 if (strcmp(p, ".") != 0) { 190 while (cur && 191 strcmp(cur->name, p) != 0) { 192 cur = cur->next; 193 } 194 } 195 if (cur == NULL || cur->type != F_DIR) { 196 mtree_err("%s: %s", tname, 197 strerror(ENOENT)); 198 } 199 *e = '/'; 200 pathparent = cur; 201 cur = cur->child; 202 } 203 if (*p == '\0') 204 mtree_err("%s: empty leaf element", tname); 205 } 206 207 if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL) 208 mtree_err("%s", strerror(errno)); 209 *centry = ginfo; 210 centry->lineno = mtree_lineno; 211 strcpy(centry->name, p); 212#define MAGIC "?*[" 213 if (strpbrk(p, MAGIC)) 214 centry->flags |= F_MAGIC; 215 set(next, centry); 216 217 if (root == NULL) { 218 /* 219 * empty tree 220 */ 221 if (strcmp(centry->name, ".") != 0 || 222 centry->type != F_DIR) 223 mtree_err( 224 "root node must be the directory `.'"); 225 last = root = centry; 226 root->parent = root; 227 } else if (pathparent != NULL) { 228 /* 229 * full path entry 230 */ 231 centry->parent = pathparent; 232 cur = pathparent->child; 233 if (cur == NULL) { 234 pathparent->child = centry; 235 last = centry; 236 } else { 237 for (; cur != NULL; cur = cur->next) { 238 if (strcmp(cur->name, centry->name) 239 == 0) { 240 /* existing entry; replace */ 241 replacenode(cur, centry); 242 break; 243 } 244 if (cur->next == NULL) { 245 /* last entry; add new */ 246 cur->next = centry; 247 centry->prev = cur; 248 break; 249 } 250 } 251 last = cur; 252 while (last->next != NULL) 253 last = last->next; 254 } 255 } else if (strcmp(centry->name, ".") == 0) { 256 /* 257 * duplicate "." entry; always replace 258 */ 259 replacenode(root, centry); 260 } else if (last->type == F_DIR && !(last->flags & F_DONE)) { 261 /* 262 * new relative child 263 * (no duplicate check) 264 */ 265 centry->parent = last; 266 last = last->child = centry; 267 } else { 268 /* 269 * relative entry, up one directory 270 * (no duplicate check) 271 */ 272 centry->parent = last->parent; 273 centry->prev = last; 274 last = last->next = centry; 275 } 276 } 277 return (root); 278} 279 280void 281free_nodes(NODE *root) 282{ 283 NODE *cur, *next; 284 285 if (root == NULL) 286 return; 287 288 next = NULL; 289 for (cur = root; cur != NULL; cur = next) { 290 next = cur->next; 291 free_nodes(cur->child); 292 REPLACEPTR(cur->slink, NULL); 293 REPLACEPTR(cur->md5digest, NULL); 294 REPLACEPTR(cur->rmd160digest, NULL); 295 REPLACEPTR(cur->sha1digest, NULL); 296 REPLACEPTR(cur->sha256digest, NULL); 297 REPLACEPTR(cur->sha384digest, NULL); 298 REPLACEPTR(cur->sha512digest, NULL); 299 REPLACEPTR(cur->tags, NULL); 300 REPLACEPTR(cur, NULL); 301 } 302} 303 304/* 305 * dump_nodes -- 306 * dump the NODEs from `cur', based in the directory `dir'. 307 * if pathlast is none zero, print the path last, otherwise print 308 * it first. 309 */ 310void 311dump_nodes(const char *dir, NODE *root, int pathlast) 312{ 313 NODE *cur; 314 char path[MAXPATHLEN]; 315 const char *name; 316 317 for (cur = root; cur != NULL; cur = cur->next) { 318 if (cur->type != F_DIR && !matchtags(cur)) 319 continue; 320 321 if (snprintf(path, sizeof(path), "%s%s%s", 322 dir, *dir ? "/" : "", cur->name) 323 >= sizeof(path)) 324 mtree_err("Pathname too long."); 325 326 if (!pathlast) 327 printf("%s ", vispath(path)); 328 329#define MATCHFLAG(f) ((keys & (f)) && (cur->flags & (f))) 330 if (MATCHFLAG(F_TYPE)) 331 printf("type=%s ", nodetype(cur->type)); 332 if (MATCHFLAG(F_UID | F_UNAME)) { 333 if (keys & F_UNAME && 334 (name = user_from_uid(cur->st_uid, 1)) != NULL) 335 printf("uname=%s ", name); 336 else 337 printf("uid=%u ", cur->st_uid); 338 } 339 if (MATCHFLAG(F_GID | F_GNAME)) { 340 if (keys & F_GNAME && 341 (name = group_from_gid(cur->st_gid, 1)) != NULL) 342 printf("gname=%s ", name); 343 else 344 printf("gid=%u ", cur->st_gid); 345 } 346 if (MATCHFLAG(F_MODE)) 347 printf("mode=%#o ", cur->st_mode); 348 if (MATCHFLAG(F_DEV) && 349 (cur->type == F_BLOCK || cur->type == F_CHAR)) 350 printf("device=%#x ", cur->st_rdev); 351 if (MATCHFLAG(F_NLINK)) 352 printf("nlink=%d ", cur->st_nlink); 353 if (MATCHFLAG(F_SLINK)) 354 printf("link=%s ", vispath(cur->slink)); 355 if (MATCHFLAG(F_SIZE)) 356 printf("size=%lld ", (long long)cur->st_size); 357 if (MATCHFLAG(F_TIME)) 358 printf("time=%ld.%ld ", (long)cur->st_mtimespec.tv_sec, 359 cur->st_mtimespec.tv_nsec); 360 if (MATCHFLAG(F_CKSUM)) 361 printf("cksum=%lu ", cur->cksum); 362 if (MATCHFLAG(F_MD5)) 363 printf("md5=%s ", cur->md5digest); 364 if (MATCHFLAG(F_RMD160)) 365 printf("rmd160=%s ", cur->rmd160digest); 366 if (MATCHFLAG(F_SHA1)) 367 printf("sha1=%s ", cur->sha1digest); 368 if (MATCHFLAG(F_SHA256)) 369 printf("sha256=%s ", cur->sha256digest); 370 if (MATCHFLAG(F_SHA384)) 371 printf("sha384=%s ", cur->sha384digest); 372 if (MATCHFLAG(F_SHA512)) 373 printf("sha512=%s ", cur->sha512digest); 374 if (MATCHFLAG(F_FLAGS)) 375 printf("flags=%s ", 376 flags_to_string(cur->st_flags, "none")); 377 if (MATCHFLAG(F_IGN)) 378 printf("ignore "); 379 if (MATCHFLAG(F_OPT)) 380 printf("optional "); 381 if (MATCHFLAG(F_TAGS)) 382 printf("tags=%s ", cur->tags); 383 puts(pathlast ? vispath(path) : ""); 384 385 if (cur->child) 386 dump_nodes(path, cur->child, pathlast); 387 } 388} 389 390/* 391 * vispath -- 392 * strsvis(3) encodes path, which must not be longer than MAXPATHLEN 393 * characters long, and returns a pointer to a static buffer containing 394 * the result. 395 */ 396char * 397vispath(const char *path) 398{ 399 const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' }; 400 static char pathbuf[4*MAXPATHLEN + 1]; 401 402 strsvis(pathbuf, path, VIS_CSTYLE, extra); 403 return(pathbuf); 404} 405 406 407static dev_t 408parsedev(char *arg) 409{ 410#define MAX_PACK_ARGS 3 411 u_long numbers[MAX_PACK_ARGS]; 412 char *p, *ep, *dev; 413 int argc; 414 pack_t *pack; 415 dev_t result; 416 const char *error = NULL; 417 418 if ((dev = strchr(arg, ',')) != NULL) { 419 *dev++='\0'; 420 if ((pack = pack_find(arg)) == NULL) 421 mtree_err("unknown format `%s'", arg); 422 argc = 0; 423 while ((p = strsep(&dev, ",")) != NULL) { 424 if (*p == '\0') 425 mtree_err("missing number"); 426 numbers[argc++] = strtoul(p, &ep, 0); 427 if (*ep != '\0') 428 mtree_err("invalid number `%s'", 429 p); 430 if (argc > MAX_PACK_ARGS) 431 mtree_err("too many arguments"); 432 } 433 if (argc < 2) 434 mtree_err("not enough arguments"); 435 result = (*pack)(argc, numbers, &error); 436 if (error != NULL) 437 mtree_err(error); 438 } else { 439 result = (dev_t)strtoul(arg, &ep, 0); 440 if (*ep != '\0') 441 mtree_err("invalid device `%s'", arg); 442 } 443 return (result); 444} 445 446static void 447replacenode(NODE *cur, NODE *new) 448{ 449 450#define REPLACE(x) cur->x = new->x 451#define REPLACESTR(x) REPLACEPTR(cur->x,new->x) 452 453 if (cur->type != new->type) { 454 if (mtree_Mflag) { 455 /* 456 * merge entries with different types; we 457 * don't want children retained in this case. 458 */ 459 REPLACE(type); 460 free_nodes(cur->child); 461 cur->child = NULL; 462 } else { 463 mtree_err( 464 "existing entry for `%s', type `%s'" 465 " does not match type `%s'", 466 cur->name, nodetype(cur->type), 467 nodetype(new->type)); 468 } 469 } 470 471 REPLACE(st_size); 472 REPLACE(st_mtimespec); 473 REPLACESTR(slink); 474 if (cur->slink != NULL) { 475 if ((cur->slink = strdup(new->slink)) == NULL) 476 mtree_err("memory allocation error"); 477 if (strunvis(cur->slink, new->slink) == -1) 478 mtree_err("strunvis failed on `%s'", new->slink); 479 free(new->slink); 480 } 481 REPLACE(st_uid); 482 REPLACE(st_gid); 483 REPLACE(st_mode); 484 REPLACE(st_rdev); 485 REPLACE(st_flags); 486 REPLACE(st_nlink); 487 REPLACE(cksum); 488 REPLACESTR(md5digest); 489 REPLACESTR(rmd160digest); 490 REPLACESTR(sha1digest); 491 REPLACESTR(sha256digest); 492 REPLACESTR(sha384digest); 493 REPLACESTR(sha512digest); 494 REPLACESTR(tags); 495 REPLACE(lineno); 496 REPLACE(flags); 497 free(new); 498} 499 500static void 501set(char *t, NODE *ip) 502{ 503 int type, value, len; 504 gid_t gid; 505 uid_t uid; 506 char *kw, *val, *md, *ep; 507 void *m; 508 509 while ((kw = strsep(&t, "= \t")) != NULL) { 510 if (*kw == '\0') 511 continue; 512 if (strcmp(kw, "all") == 0) 513 mtree_err("invalid keyword `all'"); 514 ip->flags |= type = parsekey(kw, &value); 515 if (!value) 516 /* Just set flag bit (F_IGN and F_OPT) */ 517 continue; 518 while ((val = strsep(&t, " \t")) != NULL && *val == '\0') 519 continue; 520 if (val == NULL) 521 mtree_err("missing value"); 522 switch (type) { 523 case F_CKSUM: 524 ip->cksum = strtoul(val, &ep, 10); 525 if (*ep) 526 mtree_err("invalid checksum `%s'", val); 527 break; 528 case F_DEV: 529 ip->st_rdev = parsedev(val); 530 break; 531 case F_FLAGS: 532 if (strcmp("none", val) == 0) 533 ip->st_flags = 0; 534 else if (string_to_flags(&val, &ip->st_flags, NULL) 535 != 0) 536 mtree_err("invalid flag `%s'", val); 537 break; 538 case F_GID: 539 ip->st_gid = (gid_t)strtoul(val, &ep, 10); 540 if (*ep) 541 mtree_err("invalid gid `%s'", val); 542 break; 543 case F_GNAME: 544 if (mtree_Wflag) /* don't parse if whacking */ 545 break; 546 if (gid_from_group(val, &gid) == -1) 547 mtree_err("unknown group `%s'", val); 548 ip->st_gid = gid; 549 break; 550 case F_MD5: 551 if (val[0]=='0' && val[1]=='x') 552 md=&val[2]; 553 else 554 md=val; 555 if ((ip->md5digest = strdup(md)) == NULL) 556 mtree_err("memory allocation error"); 557 break; 558 case F_MODE: 559 if ((m = setmode(val)) == NULL) 560 mtree_err("cannot set file mode `%s' (%s)", 561 val, strerror(errno)); 562 ip->st_mode = getmode(m, 0); 563 free(m); 564 break; 565 case F_NLINK: 566 ip->st_nlink = (nlink_t)strtoul(val, &ep, 10); 567 if (*ep) 568 mtree_err("invalid link count `%s'", val); 569 break; 570 case F_RMD160: 571 if (val[0]=='0' && val[1]=='x') 572 md=&val[2]; 573 else 574 md=val; 575 if ((ip->rmd160digest = strdup(md)) == NULL) 576 mtree_err("memory allocation error"); 577 break; 578 case F_SHA1: 579 if (val[0]=='0' && val[1]=='x') 580 md=&val[2]; 581 else 582 md=val; 583 if ((ip->sha1digest = strdup(md)) == NULL) 584 mtree_err("memory allocation error"); 585 break; 586 case F_SIZE: 587 ip->st_size = (off_t)strtoll(val, &ep, 10); 588 if (*ep) 589 mtree_err("invalid size `%s'", val); 590 break; 591 case F_SLINK: 592 if ((ip->slink = strdup(val)) == NULL) 593 mtree_err("memory allocation error"); 594 if (strunvis(ip->slink, val) == -1) 595 mtree_err("strunvis failed on `%s'", val); 596 break; 597 case F_TAGS: 598 len = strlen(val) + 3; /* "," + str + ",\0" */ 599 if ((ip->tags = malloc(len)) == NULL) 600 mtree_err("memory allocation error"); 601 snprintf(ip->tags, len, ",%s,", val); 602 break; 603 case F_TIME: 604 ip->st_mtimespec.tv_sec = 605 (time_t)strtoul(val, &ep, 10); 606 if (*ep != '.') 607 mtree_err("invalid time `%s'", val); 608 val = ep + 1; 609 ip->st_mtimespec.tv_nsec = strtoul(val, &ep, 10); 610 if (*ep) 611 mtree_err("invalid time `%s'", val); 612 break; 613 case F_TYPE: 614 ip->type = parsetype(val); 615 break; 616 case F_UID: 617 ip->st_uid = (uid_t)strtoul(val, &ep, 10); 618 if (*ep) 619 mtree_err("invalid uid `%s'", val); 620 break; 621 case F_UNAME: 622 if (mtree_Wflag) /* don't parse if whacking */ 623 break; 624 if (uid_from_user(val, &uid) == -1) 625 mtree_err("unknown user `%s'", val); 626 ip->st_uid = uid; 627 break; 628 case F_SHA256: 629 if (val[0]=='0' && val[1]=='x') 630 md=&val[2]; 631 else 632 md=val; 633 if ((ip->sha256digest = strdup(md)) == NULL) 634 mtree_err("memory allocation error"); 635 break; 636 case F_SHA384: 637 if (val[0]=='0' && val[1]=='x') 638 md=&val[2]; 639 else 640 md=val; 641 if ((ip->sha384digest = strdup(md)) == NULL) 642 mtree_err("memory allocation error"); 643 break; 644 case F_SHA512: 645 if (val[0]=='0' && val[1]=='x') 646 md=&val[2]; 647 else 648 md=val; 649 if ((ip->sha512digest = strdup(md)) == NULL) 650 mtree_err("memory allocation error"); 651 break; 652 default: 653 mtree_err( 654 "set(): unsupported key type 0x%x (INTERNAL ERROR)", 655 type); 656 /* NOTREACHED */ 657 } 658 } 659} 660 661static void 662unset(char *t, NODE *ip) 663{ 664 char *p; 665 666 while ((p = strsep(&t, " \t")) != NULL) { 667 if (*p == '\0') 668 continue; 669 ip->flags &= ~parsekey(p, NULL); 670 } 671} 672