void write_directory_file (void) { FILE *fp = listed_incremental_stream; char buf[UINTMAX_STRSIZE_BOUND]; char *s; if (! fp) return; if (fseeko (fp, 0L, SEEK_SET) != 0) seek_error (listed_incremental_option); if (sys_truncate (fileno (fp)) != 0) truncate_error (listed_incremental_option); fprintf (fp, "%s-%s-%d\n", PACKAGE_NAME, PACKAGE_VERSION, TAR_INCREMENTAL_VERSION); s = (TYPE_SIGNED (time_t) ? imaxtostr (start_time.tv_sec, buf) : umaxtostr (start_time.tv_sec, buf)); fwrite (s, strlen (s) + 1, 1, fp); s = umaxtostr (start_time.tv_nsec, buf); fwrite (s, strlen (s) + 1, 1, fp); if (! ferror (fp) && directory_table) hash_do_for_each (directory_table, write_directory_file_entry, fp); if (ferror (fp)) write_error (listed_incremental_option); if (fclose (fp) != 0) close_error (listed_incremental_option); }
static void out_of_range_header (char const *keyword, char const *value, uintmax_t minus_minval, uintmax_t maxval) { char minval_buf[UINTMAX_STRSIZE_BOUND + 1]; char maxval_buf[UINTMAX_STRSIZE_BOUND]; char *minval_string = umaxtostr (minus_minval, minval_buf + 1); char *maxval_string = umaxtostr (maxval, maxval_buf); if (minus_minval) *--minval_string = '-'; /* TRANSLATORS: The first %s is the pax extended header keyword (atime, gid, etc.). */ ERROR ((0, 0, _("Extended header %s=%s is out of range %s..%s"), keyword, value, minval_string, maxval_string)); }
static void xheader_print_n (struct xheader *xhdr, char const *keyword, char const *value, size_t vsize) { size_t p; size_t n = 0; char nbuf[UINTMAX_STRSIZE_BOUND]; char const *np; size_t len, klen; keyword = xattr_encode_keyword (keyword); klen = strlen (keyword); len = klen + vsize + 3; /* ' ' + '=' + '\n' */ do { p = n; np = umaxtostr (len + p, nbuf); n = nbuf + sizeof nbuf - 1 - np; } while (n != p); x_obstack_grow (xhdr, np, n); x_obstack_1grow (xhdr, ' '); x_obstack_grow (xhdr, keyword, klen); x_obstack_1grow (xhdr, '='); x_obstack_grow (xhdr, value, vsize); x_obstack_1grow (xhdr, '\n'); }
extern char * uid_to_name (uid_t uid) { char buf[INT_BUFSIZE_BOUND (intmax_t)]; struct passwd *pwd = getpwuid (uid); return xstrdup (pwd ? pwd->pw_name : TYPE_SIGNED (uid_t) ? imaxtostr (uid, buf) : umaxtostr (uid, buf)); }
extern char * gid_to_name (gid_t gid) { char buf[INT_BUFSIZE_BOUND (intmax_t)]; struct group *grp = getgrgid (gid); return xstrdup (grp ? grp->gr_name : TYPE_SIGNED (gid_t) ? imaxtostr (gid, buf) : umaxtostr (gid, buf)); }
/* %o */ static char * hdr_size (struct header_call_args *args, void *data) { size_t m_size; char buf[UINTMAX_STRSIZE_BOUND]; mu_message_size (args->msg, &m_size); return header_buf_string (args, umaxtostr (m_size, buf)); }
/* Output incremental data for the directory ENTRY to the file DATA. Return nonzero if successful, preserving errno on write failure. */ static bool write_directory_file_entry (void *entry, void *data) { struct directory const *directory = entry; FILE *fp = data; if (DIR_IS_FOUND (directory)) { char buf[UINTMAX_STRSIZE_BOUND]; char *s; s = DIR_IS_NFS (directory) ? "1" : "0"; fwrite (s, 2, 1, fp); s = (TYPE_SIGNED (time_t) ? imaxtostr (directory->mtime.tv_sec, buf) : umaxtostr (directory->mtime.tv_sec, buf)); fwrite (s, strlen (s) + 1, 1, fp); s = umaxtostr (directory->mtime.tv_nsec, buf); fwrite (s, strlen (s) + 1, 1, fp); s = umaxtostr (directory->device_number, buf); fwrite (s, strlen (s) + 1, 1, fp); s = umaxtostr (directory->inode_number, buf); fwrite (s, strlen (s) + 1, 1, fp); fwrite (directory->name, strlen (directory->name) + 1, 1, fp); if (directory->dump) { const char *p; dumpdir_iter_t itr; for (p = dumpdir_first (directory->dump, 0, &itr); p; p = dumpdir_next (itr)) fwrite (p, strlen (p) + 1, 1, fp); free (itr); } fwrite ("\0\0", 2, 1, fp); } return ! ferror (fp); }
char * sysinttostr (uintmax_t value, intmax_t minval, uintmax_t maxval, char buf[SYSINT_BUFSIZE]) { if (value <= maxval) return umaxtostr (value, buf); else { intmax_t i = value - minval; return imaxtostr (i + minval, buf); } }
bool xheader_string_end (struct xheader *xhdr, char const *keyword) { uintmax_t len; uintmax_t p; uintmax_t n = 0; size_t size; char nbuf[UINTMAX_STRSIZE_BOUND]; char const *np; char *cp; if (xhdr->buffer) return false; xheader_init (xhdr); len = strlen (keyword) + xhdr->string_length + 3; /* ' ' + '=' + '\n' */ do { p = n; np = umaxtostr (len + p, nbuf); n = nbuf + sizeof nbuf - 1 - np; } while (n != p); p = strlen (keyword) + n + 2; size = p; if (size != p) { ERROR ((0, 0, _("Generated keyword/value pair is too long (keyword=%s, length=%s)"), keyword, nbuf)); obstack_free (xhdr->stk, obstack_finish (xhdr->stk)); return false; } x_obstack_blank (xhdr, p); x_obstack_1grow (xhdr, '\n'); cp = obstack_next_free (xhdr->stk) - xhdr->string_length - p - 1; memmove (cp + p, cp, xhdr->string_length); cp = stpcpy (cp, np); *cp++ = ' '; cp = stpcpy (cp, keyword); *cp++ = '='; return true; }
char const * code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND]) { time_t s = t.tv_sec; int ns = t.tv_nsec; char *np; bool negative = s < 0; /* ignore invalid values of ns */ if (BILLION <= ns || ns < 0) ns = 0; if (negative && ns != 0) { s++; ns = BILLION - ns; } np = umaxtostr (negative ? - (uintmax_t) s : (uintmax_t) s, sbuf + 1); if (negative) *--np = '-'; code_ns_fraction (ns, sbuf + UINTMAX_STRSIZE_BOUND); return np; }
/* %m */ static char * hdr_number (struct header_call_args *args, void *data) { char buf[UINTMAX_STRSIZE_BOUND]; return header_buf_string (args, umaxtostr (args->mspec->msg_part[0], buf)); }
static int build_algparm (pskc_key_t * kp, xmlNodePtr keyp) { const char *suite = pskc_get_key_algparm_suite (kp); int chall_encoding_p; pskc_valueformat chall_encoding = pskc_get_key_algparm_chall_encoding (kp, &chall_encoding_p); int chall_min_p; uint32_t chall_min = pskc_get_key_algparm_chall_min (kp, &chall_min_p); int chall_max_p; uint32_t chall_max = pskc_get_key_algparm_chall_max (kp, &chall_max_p); int chall_checkdigits_p; int chall_checkdigits = pskc_get_key_algparm_chall_checkdigits (kp, &chall_checkdigits_p); int resp_encoding_p; pskc_valueformat resp_encoding = pskc_get_key_algparm_resp_encoding (kp, &resp_encoding_p); int resp_length_p; uint32_t resp_length = pskc_get_key_algparm_resp_length (kp, &resp_length_p); int resp_checkdigits_p; int resp_checkdigits = pskc_get_key_algparm_resp_checkdigits (kp, &resp_checkdigits_p); xmlNodePtr algparm; if (!suite && !chall_encoding_p && !chall_min_p && !chall_max_p && !chall_checkdigits_p && !resp_encoding_p && !resp_length_p && !resp_checkdigits_p) return PSKC_OK; algparm = xmlNewChild (keyp, NULL, BAD_CAST "AlgorithmParameters", NULL); if (suite) xmlNewTextChild (algparm, NULL, BAD_CAST "Suite", BAD_CAST suite); if (chall_encoding_p || chall_min_p || chall_max_p || resp_checkdigits_p) { xmlNodePtr chall; chall = xmlNewChild (algparm, NULL, BAD_CAST "ChallengeFormat", NULL); if (chall_encoding_p) xmlNewProp (chall, BAD_CAST "Encoding", BAD_CAST pskc_valueformat2str (chall_encoding)); if (chall_min_p) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; char *p = umaxtostr (chall_min, buf); xmlNewProp (chall, BAD_CAST "Min", BAD_CAST p); } if (chall_max_p) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; char *p = umaxtostr (chall_max, buf); xmlNewProp (chall, BAD_CAST "Max", BAD_CAST p); } if (chall_checkdigits_p && chall_checkdigits) xmlNewProp (chall, BAD_CAST "CheckDigits", BAD_CAST "true"); } if (resp_encoding_p || resp_length_p || resp_checkdigits_p) { xmlNodePtr resp; resp = xmlNewChild (algparm, NULL, BAD_CAST "ResponseFormat", NULL); if (resp_encoding_p) xmlNewProp (resp, BAD_CAST "Encoding", BAD_CAST pskc_valueformat2str (resp_encoding)); if (resp_length_p) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; char *p = umaxtostr (resp_length, buf); xmlNewProp (resp, BAD_CAST "Length", BAD_CAST p); } if (resp_checkdigits_p && resp_checkdigits) xmlNewProp (resp, BAD_CAST "CheckDigits", BAD_CAST "true"); } return PSKC_OK; }
static char const * parse_with_separator (char const *spec, char const *separator, uid_t *uid, gid_t *gid, char **username, char **groupname) { static const char *E_invalid_user = N_("invalid user"); static const char *E_invalid_group = N_("invalid group"); static const char *E_bad_spec = N_("invalid spec"); const char *error_msg; struct passwd *pwd; struct group *grp; char *u; char const *g; char *gname = NULL; uid_t unum = *uid; gid_t gnum = *gid; error_msg = NULL; *username = *groupname = NULL; /* Set U and G to nonzero length strings corresponding to user and group specifiers or to NULL. If U is not NULL, it is a newly allocated string. */ u = NULL; if (separator == NULL) { if (*spec) u = xstrdup (spec); } else { size_t ulen = separator - spec; if (ulen != 0) { u = xmemdup (spec, ulen + 1); u[ulen] = '\0'; } } g = (separator == NULL || *(separator + 1) == '\0' ? NULL : separator + 1); #ifdef __DJGPP__ /* Pretend that we are the user U whose group is G. This makes pwd and grp functions ``know'' about the UID and GID of these. */ if (u && !is_number (u)) setenv ("USER", u, 1); if (g && !is_number (g)) setenv ("GROUP", g, 1); #endif if (u != NULL) { /* If it starts with "+", skip the look-up. */ pwd = (*u == '+' ? NULL : getpwnam (u)); if (pwd == NULL) { bool use_login_group = (separator != NULL && g == NULL); if (use_login_group) { /* If there is no group, then there may not be a trailing ":", either. */ error_msg = E_bad_spec; } else { unsigned long int tmp; if (xstrtoul (u, NULL, 10, &tmp, "") == LONGINT_OK && tmp <= MAXUID && (uid_t) tmp != (uid_t) -1) unum = tmp; else error_msg = E_invalid_user; } } else { unum = pwd->pw_uid; if (g == NULL && separator != NULL) { /* A separator was given, but a group was not specified, so get the login group. */ char buf[INT_BUFSIZE_BOUND (uintmax_t)]; gnum = pwd->pw_gid; grp = getgrgid (gnum); gname = xstrdup (grp ? grp->gr_name : umaxtostr (gnum, buf)); endgrent (); } } endpwent (); } if (g != NULL && error_msg == NULL) { /* Explicit group. */ /* If it starts with "+", skip the look-up. */ grp = (*g == '+' ? NULL : getgrnam (g)); if (grp == NULL) { unsigned long int tmp; if (xstrtoul (g, NULL, 10, &tmp, "") == LONGINT_OK && tmp <= MAXGID && (gid_t) tmp != (gid_t) -1) gnum = tmp; else error_msg = E_invalid_group; } else gnum = grp->gr_gid; endgrent (); /* Save a file descriptor. */ gname = xstrdup (g); } if (error_msg == NULL) { *uid = unum; *gid = gnum; *username = u; *groupname = gname; u = NULL; } else free (gname); free (u); return _(error_msg); }
/* Convert a gid_t to string. Do not use this function directly. Instead, use it via the gidtostr macro. Beware that it returns a pointer to static storage. */ static char * gidtostr_ptr (gid_t const *gid) { static char buf[INT_BUFSIZE_BOUND (uintmax_t)]; return umaxtostr (*gid, buf); }
char * xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n) { char *buf; size_t len = strlen (fmt); char *q; const char *p; char *dirp = NULL; char *dir = NULL; char *base = NULL; char pidbuf[UINTMAX_STRSIZE_BOUND]; char const *pptr = NULL; char nbuf[UINTMAX_STRSIZE_BOUND]; char const *nptr = NULL; for (p = fmt; *p && (p = strchr (p, '%')); ) { switch (p[1]) { case '%': len--; break; case 'd': if (st) { if (!dirp) dirp = dir_name (st->orig_file_name); dir = safer_name_suffix (dirp, false, absolute_names_option); len += strlen (dir) - 2; } break; case 'f': if (st) { base = last_component (st->orig_file_name); len += strlen (base) - 2; } break; case 'p': pptr = umaxtostr (getpid (), pidbuf); len += pidbuf + sizeof pidbuf - 1 - pptr - 2; break; case 'n': nptr = umaxtostr (n, nbuf); len += nbuf + sizeof nbuf - 1 - nptr - 2; break; } p++; } buf = xmalloc (len + 1); for (q = buf, p = fmt; *p; ) { if (*p == '%') { switch (p[1]) { case '%': *q++ = *p++; p++; break; case 'd': if (dir) q = stpcpy (q, dir); p += 2; break; case 'f': if (base) q = stpcpy (q, base); p += 2; break; case 'p': q = stpcpy (q, pptr); p += 2; break; case 'n': q = stpcpy (q, nptr); p += 2; break; default: *q++ = *p++; if (*p) *q++ = *p++; } } else *q++ = *p++; } free (dirp); /* Do not allow it to end in a slash */ while (q > buf && ISSLASH (q[-1])) q--; *q = 0; return buf; }
static bool read_num (FILE *fp, char const *fieldname, intmax_t min_val, uintmax_t max_val, intmax_t *pval) { int i; char buf[INT_BUFSIZE_BOUND (intmax_t)]; char offbuf[INT_BUFSIZE_BOUND (off_t)]; char minbuf[INT_BUFSIZE_BOUND (intmax_t)]; char maxbuf[INT_BUFSIZE_BOUND (intmax_t)]; int conversion_errno; int c = getc (fp); bool negative = c == '-'; for (i = 0; (i == 0 && negative) || ISDIGIT (c); i++) { buf[i] = c; if (i == sizeof buf - 1) FATAL_ERROR ((0, 0, _("%s: byte %s: %s %.*s... too long"), quotearg_colon (listed_incremental_option), offtostr (ftello (fp), offbuf), fieldname, i + 1, buf)); c = getc (fp); } buf[i] = 0; if (c < 0) { if (ferror (fp)) read_fatal (listed_incremental_option); if (i != 0) FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (listed_incremental_option), _("Unexpected EOF in snapshot file"))); return false; } if (c) { unsigned uc = c; FATAL_ERROR ((0, 0, _("%s: byte %s: %s %s followed by invalid byte 0x%02x"), quotearg_colon (listed_incremental_option), offtostr (ftello (fp), offbuf), fieldname, buf, uc)); } *pval = strtosysint (buf, NULL, min_val, max_val); conversion_errno = errno; switch (conversion_errno) { case ERANGE: FATAL_ERROR ((0, conversion_errno, _("%s: byte %s: (valid range %s..%s)\n\t%s %s"), quotearg_colon (listed_incremental_option), offtostr (ftello (fp), offbuf), imaxtostr (min_val, minbuf), umaxtostr (max_val, maxbuf), fieldname, buf)); default: FATAL_ERROR ((0, conversion_errno, _("%s: byte %s: %s %s"), quotearg_colon (listed_incremental_option), offtostr (ftello (fp), offbuf), fieldname, buf)); case 0: break; } return true; }
static int build_data (pskc_key_t * kp, xmlNodePtr keyp) { const char *b64secret = pskc_get_key_data_b64secret (kp); int counter_p; uint64_t counter = pskc_get_key_data_counter (kp, &counter_p); int t_p; uint32_t t = pskc_get_key_data_time (kp, &t_p); int tinterval_p; uint32_t tinterval = pskc_get_key_data_timeinterval (kp, &tinterval_p); int tdrift_p; uint32_t tdrift = pskc_get_key_data_timedrift (kp, &tdrift_p); xmlNodePtr data, sub; if (!b64secret && !counter_p && !t_p && !tinterval_p && !tdrift_p) return PSKC_OK; data = xmlNewChild (keyp, NULL, BAD_CAST "Data", NULL); if (b64secret) { sub = xmlNewChild (data, NULL, BAD_CAST "Secret", NULL); xmlNewTextChild (sub, NULL, BAD_CAST "PlainValue", BAD_CAST b64secret); } if (counter_p) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; char *p = umaxtostr (counter, buf); sub = xmlNewChild (data, NULL, BAD_CAST "Counter", NULL); xmlNewTextChild (sub, NULL, BAD_CAST "PlainValue", BAD_CAST p); } if (t_p) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; char *p = umaxtostr (t, buf); sub = xmlNewChild (data, NULL, BAD_CAST "Time", NULL); xmlNewTextChild (sub, NULL, BAD_CAST "PlainValue", BAD_CAST p); } if (tinterval_p) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; char *p = umaxtostr (tinterval, buf); sub = xmlNewChild (data, NULL, BAD_CAST "TimeInterval", NULL); xmlNewTextChild (sub, NULL, BAD_CAST "PlainValue", BAD_CAST p); } if (tdrift_p) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; char *p = umaxtostr (tdrift, buf); sub = xmlNewChild (data, NULL, BAD_CAST "TimeDrift", NULL); xmlNewTextChild (sub, NULL, BAD_CAST "PlainValue", BAD_CAST p); } return PSKC_OK; }
static void code_num (uintmax_t value, char const *keyword, struct xheader *xhdr) { char sbuf[UINTMAX_STRSIZE_BOUND]; xheader_print (xhdr, keyword, umaxtostr (value, sbuf)); }
static int build_policy (pskc_key_t * kp, xmlNodePtr keyp) { int keyusage_p; int keyusages = pskc_get_key_policy_keyusages (kp, &keyusage_p); const struct tm *startdate = pskc_get_key_policy_startdate (kp); const struct tm *expirydate = pskc_get_key_policy_expirydate (kp); const char *pinkeyid = pskc_get_key_policy_pinkeyid (kp); int pinusagemode_p; pskc_pinusagemode pinusagemode = pskc_get_key_policy_pinusagemode (kp, &pinusagemode_p); int attempts_p; uint32_t attempts = pskc_get_key_policy_pinmaxfailedattempts (kp, &attempts_p); int pinmin_p; uint32_t pinmin = pskc_get_key_policy_pinminlength (kp, &pinmin_p); int pinmax_p; uint32_t pinmax = pskc_get_key_policy_pinmaxlength (kp, &pinmax_p); int pinencoding_p; pskc_valueformat pinencoding = pskc_get_key_policy_pinencoding (kp, &pinencoding_p); int numberoftransactions_p; uint64_t numberoftransactions = pskc_get_key_policy_numberoftransactions (kp, &numberoftransactions_p); xmlNodePtr policy, pinpolicy; if (!keyusage_p && !startdate && !expirydate && !pinkeyid && !pinusagemode_p && !attempts_p && !pinmin_p && !pinmax_p && !pinencoding_p) return PSKC_OK; policy = xmlNewChild (keyp, NULL, BAD_CAST "Policy", NULL); if (startdate) { char t[100]; strftime (t, sizeof (t), "%Y-%m-%dT%H:%M:%SZ", startdate); xmlNewTextChild (policy, NULL, BAD_CAST "StartDate", BAD_CAST t); } if (expirydate) { char t[100]; strftime (t, sizeof (t), "%Y-%m-%dT%H:%M:%SZ", expirydate); xmlNewTextChild (policy, NULL, BAD_CAST "ExpiryDate", BAD_CAST t); } if (pinkeyid || pinusagemode_p || attempts_p || pinmin_p || pinmax_p || pinencoding_p) { pinpolicy = xmlNewChild (policy, NULL, BAD_CAST "PINPolicy", NULL); if (pinkeyid) xmlNewProp (pinpolicy, BAD_CAST "PINKeyId", BAD_CAST pinkeyid); if (pinusagemode_p) xmlNewProp (pinpolicy, BAD_CAST "PINUsageMode", BAD_CAST pskc_pinusagemode2str (pinusagemode)); if (attempts_p) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; char *p = umaxtostr (attempts, buf); xmlNewProp (pinpolicy, BAD_CAST "MaxFailedAttempts", BAD_CAST p); } if (pinmin_p) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; char *p = umaxtostr (pinmin, buf); xmlNewProp (pinpolicy, BAD_CAST "MinLength", BAD_CAST p); } if (pinmax_p) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; char *p = umaxtostr (pinmax, buf); xmlNewProp (pinpolicy, BAD_CAST "MaxLength", BAD_CAST p); } if (pinencoding_p) xmlNewProp (pinpolicy, BAD_CAST "PINEncoding", BAD_CAST pskc_valueformat2str (pinencoding)); } if (keyusage_p) { int i; for (i = 1; i <= PSKC_KEYUSAGE_LAST; i = i << 1) { const char *keyusage_str = pskc_keyusage2str (i); if (keyusages & i) xmlNewTextChild (policy, NULL, BAD_CAST "KeyUsage", BAD_CAST keyusage_str); } } if (numberoftransactions_p) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; char *p = umaxtostr (numberoftransactions, buf); xmlNewTextChild (policy, NULL, BAD_CAST "NumberOfTransactions", BAD_CAST p); } return PSKC_OK; }