static int sbuf_copy_lines(struct sbuf *to, const char *from, int N) { int cnt = 0; int i; if (N == 0) return (0); for (i = 0; from[i] != '\0'; i++) { if (from[i] == '\n') { cnt++; continue; } if (cnt == N) break; } if (to == NULL) return (i); if (sbuf_len(to) > 0 && sbuf_data(to)[sbuf_len(to)-1] != '\n') sbuf_putc(to, '\n'); sbuf_bcat(to, from, i); sbuf_finish(to); return (i); }
static int ucl_sbuf_append_len(const unsigned char *str, size_t len, void *data) { struct sbuf *buf = data; sbuf_bcat(buf, str, len); return (0); }
/* * Copy a byte string into an sbuf. */ int sbuf_bcpy(struct sbuf *s, const char *str, size_t len) { assert_sbuf_integrity(s); assert_sbuf_state(s, 0); sbuf_clear(s); return (sbuf_bcat(s, str, len)); }
/* * Copy a byte string into an sbuf. */ int sbuf_bcpy(struct sbuf *s, const void *buf, size_t len) { assert_sbuf_integrity(s); assert_sbuf_state(s, 0); sbuf_clear(s); return (sbuf_bcat(s, buf, len)); }
static void subst_packagesite(const char *abi) { struct sbuf *newval; const char *variable_string; const char *oldval; if (c[PACKAGESITE].value != NULL) oldval = c[PACKAGESITE].value; else oldval = c[PACKAGESITE].val; if ((variable_string = strstr(oldval, "${ABI}")) == NULL) return; newval = sbuf_new_auto(); sbuf_bcat(newval, oldval, variable_string - oldval); sbuf_cat(newval, abi); sbuf_cat(newval, variable_string + strlen("${ABI}")); sbuf_finish(newval); free(c[PACKAGESITE].value); c[PACKAGESITE].value = strdup(sbuf_data(newval)); }
/* mtree_resolve() sets errno to indicate why NULL was returned. */ static char * mtree_resolve(const char *spec, int *istemp) { struct sbuf *sb; char *res, *var; const char *base, *p, *v; size_t len; int c, error, quoted, subst; len = strlen(spec); if (len == 0) { errno = EINVAL; return (NULL); } c = (len > 1) ? (spec[0] == spec[len - 1]) ? spec[0] : 0 : 0; *istemp = (c == '`') ? 1 : 0; subst = (c == '`' || c == '"') ? 1 : 0; quoted = (subst || c == '\'') ? 1 : 0; if (!subst) { res = strdup(spec + quoted); if (res != NULL && quoted) res[len - 2] = '\0'; return (res); } sb = sbuf_new_auto(); if (sb == NULL) { errno = ENOMEM; return (NULL); } base = spec + 1; len -= 2; error = 0; while (len > 0) { p = strchr(base, '$'); if (p == NULL) { sbuf_bcat(sb, base, len); base += len; len = 0; continue; } /* The following is safe. spec always starts with a quote. */ if (p[-1] == '\\') p--; if (base != p) { sbuf_bcat(sb, base, p - base); len -= p - base; base = p; } if (*p == '\\') { sbuf_putc(sb, '$'); base += 2; len -= 2; continue; } /* Skip the '$'. */ base++; len--; /* Handle ${X} vs $X. */ v = base; if (*base == '{') { p = strchr(v, '}'); if (p == NULL) p = v; } else p = v; len -= (p + 1) - base; base = p + 1; if (v == p) { sbuf_putc(sb, *v); continue; } error = ENOMEM; var = calloc(p - v, 1); if (var == NULL) break; memcpy(var, v + 1, p - v - 1); if (strcmp(var, ".CURDIR") == 0) { res = getcwd(NULL, 0); if (res == NULL) break; } else if (strcmp(var, ".PROG") == 0) { res = strdup(getprogname()); if (res == NULL) break; } else { v = getenv(var); if (v != NULL) { res = strdup(v); if (res == NULL) break; } else res = NULL; } error = 0; if (res != NULL) { sbuf_cat(sb, res); free(res); } free(var); } sbuf_finish(sb); res = (error == 0) ? strdup(sbuf_data(sb)) : NULL; sbuf_delete(sb); if (res == NULL) errno = ENOMEM; return (res); }
int main(int argc, char *argv[]) { #define STDIN_BUF_SZ 1024 char stdin_data[STDIN_BUF_SZ]; char *p; const char *options, *attrname; size_t len; ssize_t ret; int ch, error, i, arg_counter, attrnamespace, minargc; char *visbuf = NULL; int visbuflen = 0; char *buf = NULL; int buflen = 0; struct sbuf *attrvalue = NULL; int flag_force = 0; int flag_nofollow = 0; int flag_null = 0; int count_quiet = 0; int flag_from_stdin = 0; int flag_string = 0; int flag_hex = 0; p = basename(argv[0]); if (p == NULL) p = argv[0]; if (!strcmp(p, "getextattr")) { what = EAGET; options = "fhqsx"; minargc = 3; } else if (!strcmp(p, "setextattr")) { what = EASET; options = "fhinq"; minargc = 3; } else if (!strcmp(p, "rmextattr")) { what = EARM; options = "fhq"; minargc = 3; } else if (!strcmp(p, "lsextattr")) { what = EALS; options = "fhq"; minargc = 2; } else { usage(); } while ((ch = getopt(argc, argv, options)) != -1) { switch (ch) { case 'f': flag_force = 1; break; case 'h': flag_nofollow = 1; break; case 'i': flag_from_stdin = 1; break; case 'n': flag_null = 1; break; case 'q': count_quiet += 1; break; case 's': flag_string = 1; break; case 'x': flag_hex = 1; break; case '?': default: usage(); } } argc -= optind; argv += optind; if (what == EASET && flag_from_stdin == 0) minargc++; if (argc < minargc) usage(); error = extattr_string_to_namespace(argv[0], &attrnamespace); if (error) err(-1, "%s", argv[0]); argc--; argv++; if (what != EALS) { attrname = argv[0]; argc--; argv++; } else attrname = NULL; if (what == EASET) { attrvalue = sbuf_new_auto(); if (flag_from_stdin) { while ((error = read(0, stdin_data, STDIN_BUF_SZ)) > 0) sbuf_bcat(attrvalue, stdin_data, error); } else { sbuf_cpy(attrvalue, argv[0]); argc--; argv++; } sbuf_finish(attrvalue); } for (arg_counter = 0; arg_counter < argc; arg_counter++) { switch (what) { case EARM: if (flag_nofollow) error = extattr_delete_link(argv[arg_counter], attrnamespace, attrname); else error = extattr_delete_file(argv[arg_counter], attrnamespace, attrname); if (error >= 0) continue; break; case EASET: len = sbuf_len(attrvalue) + flag_null; if (flag_nofollow) ret = extattr_set_link(argv[arg_counter], attrnamespace, attrname, sbuf_data(attrvalue), len); else ret = extattr_set_file(argv[arg_counter], attrnamespace, attrname, sbuf_data(attrvalue), len); if (ret >= 0) { if ((size_t)ret != len && !count_quiet) { warnx("Set %zd bytes of %zu for %s", ret, len, attrname); } continue; } break; case EALS: if (flag_nofollow) ret = extattr_list_link(argv[arg_counter], attrnamespace, NULL, 0); else ret = extattr_list_file(argv[arg_counter], attrnamespace, NULL, 0); if (ret < 0) break; mkbuf(&buf, &buflen, ret); if (flag_nofollow) ret = extattr_list_link(argv[arg_counter], attrnamespace, buf, buflen); else ret = extattr_list_file(argv[arg_counter], attrnamespace, buf, buflen); if (ret < 0) break; if (!count_quiet) printf("%s\t", argv[arg_counter]); for (i = 0; i < ret; i += ch + 1) { /* The attribute name length is unsigned. */ ch = (unsigned char)buf[i]; printf("%s%*.*s", i ? "\t" : "", ch, ch, buf + i + 1); } if (!count_quiet || ret > 0) printf("\n"); continue; case EAGET: if (flag_nofollow) ret = extattr_get_link(argv[arg_counter], attrnamespace, attrname, NULL, 0); else ret = extattr_get_file(argv[arg_counter], attrnamespace, attrname, NULL, 0); if (ret < 0) break; mkbuf(&buf, &buflen, ret); if (flag_nofollow) ret = extattr_get_link(argv[arg_counter], attrnamespace, attrname, buf, buflen); else ret = extattr_get_file(argv[arg_counter], attrnamespace, attrname, buf, buflen); if (ret < 0) break; if (!count_quiet) printf("%s\t", argv[arg_counter]); if (flag_string) { mkbuf(&visbuf, &visbuflen, ret * 4 + 1); strvisx(visbuf, buf, ret, VIS_SAFE | VIS_WHITE); printf("\"%s\"", visbuf); } else if (flag_hex) { for (i = 0; i < ret; i++) printf("%s%02x", i ? " " : "", (unsigned char)buf[i]); } else { fwrite(buf, ret, 1, stdout); } if (count_quiet < 2) printf("\n"); continue; default: break; } if (!count_quiet) warn("%s: failed", argv[arg_counter]); if (flag_force) continue; return(1); } return (0); }