Example #1
0
/** RFC-2047 encode string with given charset. Only the Q encoding
 * (quoted-printable) supported at this time.
 * WARNING: this code returns a static buffer!
 */
char *rfc2047e(const char *string, const char *charset) {
    static char *out;
    char *t;
    const char *r;
    int count, minlen, idx, i;
    char **words = NULL;
    size_t l;

    assert(strlen(charset) < 40);
    if (out) {
	free(out);
	out = NULL;
    }

    /* phase 1: split original into words */
    /* 1a: count, 1b: copy */
    count = 0;
    r = string;
    while (*r) {
	count++;
	r += strcspn(r, ws);
	if (!*r) break;
	count++;
	r += strspn(r, ws);
    }
    words = (char **)xmalloc(sizeof(char *) * (count + 1));

    idx = 0;
    r = string;
    while (*r) {
	l = strcspn(r, ws);
	words[idx] = (char *)xmalloc(l+1);
	memcpy(words[idx], r, l);
	words[idx][l] = '\0';
	idx++;
	r += l;
	if (!*r) break;
	l = strspn(r, ws);
	words[idx] = (char *)xmalloc(l+1);
	memcpy(words[idx], r, l);
	words[idx][l] = '\0';
	idx++;
	r += l;
    }

    /* phase 2: encode words */
    /* a: find ranges of adjacent words to need encoding */
    /* b: encode ranges */

    idx = 0;
    while (idx < count) {
	int end; char *tmp;

	if (!needs_enc(words[idx])) {
	    idx += 2;
	    continue;
	}
	for (end = idx + 2; end < count; end += 2) {
	    if (!needs_enc(words[end]))
		break;
	}
	end -= 2;
	tmp = encode_words(&words[idx], end - idx + 1, charset);
	free(words[idx]);
	words[idx] = tmp;
	for (i = idx + 1; i <= end; i++)
	    words[i][0] = '\0';
	idx = end + 2;
    }

    l = 0;
    for (idx = 0; idx < count; idx++) {
	l += strlen(words[idx]);
    }

    /* phase 3: limit lengths */
    minlen = strlen(charset) + 7;
    /* allocate ample memory */
    out = (char *)xmalloc(l + (l / (72 - minlen) + 1) * (minlen + 2) + 1);

    if (count)
	t = stpcpy(out, words[0]);
    else
	t = out, *out = 0;

    l = strlen(out);

    for (i = 1; i < count; i+=2) {
	size_t m;
	char *tmp;

	m = strlen(words[i]);
	if (i + 1 < count)
	    m += strcspn(words[i+1], "\r\n");
	if (l + m > 74)
	    t = stpcpy(t, "\r\n");
	t = stpcpy(t, words[i]);
	if (i + 1 < count) {
	    t = stpcpy(t, words[i+1]);
	}
	tmp = strrchr(out, '\n');
	if (tmp == NULL)
	    tmp = out;
	else
	    tmp++;
	l = strlen(tmp);
    }

    /* free memory */
    for (i = 0; i < count; i++) free(words[i]);
    free(words);
    return out;
}
Example #2
0
/* Modify a Key description, replacing certain special format
   characters.  List of currently supported replacements:

   %% - Replaced by a single %
   %c - Replaced by the content of COMMENT.
   %F - Replaced by an ssh style fingerprint computed from KEY.

   The functions returns 0 on success or an error code.  On success a
   newly allocated string is stored at the address of RESULT.
 */
static gpg_error_t
modify_description (const char *in, const char *comment, const gcry_sexp_t key,
                    char **result)
{
  size_t comment_length;
  size_t in_len;
  size_t out_len;
  char *out;
  size_t i;
  int special, pass;
  char *ssh_fpr = NULL;

  comment_length = strlen (comment);
  in_len  = strlen (in);

  /* First pass calculates the length, second pass does the actual
     copying.  */
  out = NULL;
  out_len = 0;
  for (pass=0; pass < 2; pass++)
    {
      special = 0;
      for (i = 0; i < in_len; i++)
        {
          if (special)
            {
              special = 0;
              switch (in[i])
                {
                case '%':
                  if (out)
                    *out++ = '%';
                  else
                    out_len++;
                  break;

                case 'c': /* Comment.  */
                  if (out)
                    {
                      memcpy (out, comment, comment_length);
                      out += comment_length;
                    }
                  else
                    out_len += comment_length;
                  break;

                case 'F': /* SSH style fingerprint.  */
                  if (!ssh_fpr && key)
                    ssh_get_fingerprint_string (key, &ssh_fpr);
                  if (ssh_fpr)
                    {
                      if (out)
                        out = stpcpy (out, ssh_fpr);
                      else
                        out_len += strlen (ssh_fpr);
                    }
                  break;

                default: /* Invalid special sequences are kept as they are. */
                  if (out)
                    {
                      *out++ = '%';
                      *out++ = in[i];
                    }
                  else
                    out_len+=2;
                  break;
                }
            }
          else if (in[i] == '%')
            special = 1;
          else
            {
              if (out)
                *out++ = in[i];
              else
                out_len++;
            }
        }

      if (!pass)
        {
          *result = out = xtrymalloc (out_len + 1);
          if (!out)
            {
              xfree (ssh_fpr);
              return gpg_error_from_syserror ();
            }
        }
    }

  *out = 0;
  assert (*result + out_len == out);
  xfree (ssh_fpr);
  return 0;
}
Example #3
0
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;
}
Example #4
0
static gpgme_error_t
uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
	       gpgme_sig_mode_t mode, int use_armor, int use_textmode,
	       int include_certs, gpgme_ctx_t ctx /* FIXME */)
{
  engine_uiserver_t uiserver = engine;
  gpgme_error_t err = 0;
  const char *protocol;
  char *cmd;
  gpgme_key_t key;

  if (!uiserver || !in || !out)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (uiserver->protocol == GPGME_PROTOCOL_DEFAULT)
    protocol = "";
  else if (uiserver->protocol == GPGME_PROTOCOL_OpenPGP)
    protocol = " --protocol=OpenPGP";
  else if (uiserver->protocol == GPGME_PROTOCOL_CMS)
    protocol = " --protocol=CMS";
  else
    return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);

  if (asprintf (&cmd, "SIGN%s%s", protocol,
		(mode == GPGME_SIG_MODE_DETACH) ? " --detached" : "") < 0)
    return gpg_error_from_errno (errno);

  key = gpgme_signers_enum (ctx, 0);
  if (key)
    {
      const char *s = NULL;

      if (key && key->uids)
        s = key->uids->email;

      if (s && strlen (s) < 80)
        {
          char buf[100];

          strcpy (stpcpy (buf, "SENDER --info "), s);
          err = uiserver_assuan_simple_command (uiserver->assuan_ctx, buf,
                                                uiserver->status.fnc,
                                                uiserver->status.fnc_value);
        }
      else
        err = gpg_error (GPG_ERR_INV_VALUE);
      gpgme_key_unref (key);
      if (err)
      {
	free (cmd);
	return err;
      }
  }

  uiserver->input_cb.data = in;
  err = uiserver_set_fd (uiserver, INPUT_FD,
			 map_data_enc (uiserver->input_cb.data));
  if (err)
    {
      free (cmd);
      return err;
    }
  uiserver->output_cb.data = out;
  err = uiserver_set_fd (uiserver, OUTPUT_FD, use_armor ? "--armor"
			 : map_data_enc (uiserver->output_cb.data));
  if (err)
    {
      free (cmd);
      return err;
    }
  uiserver->inline_data = NULL;

  err = start (uiserver, cmd);
  free (cmd);
  return err;
}
void
nis_print_group_entry (const_nis_name group)
{
    if (group != NULL && group[0] != '\0')
    {
        size_t grouplen = strlen (group);
        char buf[grouplen + 50];
        char leafbuf[grouplen + 3];
        char domainbuf[grouplen + 3];
        nis_result *res;
        char *cp, *cp2;
        u_int i;

        cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1));
        cp = stpcpy (cp, ".groups_dir");
        cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1);
        if (cp2 != NULL && cp2[0] != '\0')
        {
            *cp++ = '.';
            stpcpy (cp, cp2);
        }
        res = nis_lookup (buf, FOLLOW_LINKS | EXPAND_NAME);

        if (res == NULL)
            return;

        if (NIS_RES_STATUS (res) != NIS_SUCCESS
                || NIS_RES_NUMOBJ (res) != 1
                || __type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ)
        {
            nis_freeresult (res);
            return;
        }

        char *mem_exp[NIS_RES_NUMOBJ (res)];
        char *mem_imp[NIS_RES_NUMOBJ (res)];
        char *mem_rec[NIS_RES_NUMOBJ (res)];
        char *nomem_exp[NIS_RES_NUMOBJ (res)];
        char *nomem_imp[NIS_RES_NUMOBJ (res)];
        char *nomem_rec[NIS_RES_NUMOBJ (res)];
        unsigned long mem_exp_cnt = 0, mem_imp_cnt = 0, mem_rec_cnt = 0;
        unsigned long nomem_exp_cnt = 0, nomem_imp_cnt = 0, nomem_rec_cnt = 0;

        for (i = 0;
                i < NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len; ++i)
        {
            char *grmem =
                NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val[i];
            int neg = grmem[0] == '-';

            switch (grmem[neg])
            {
            case '*':
                if (neg)
                {
                    nomem_imp[nomem_imp_cnt] = grmem;
                    ++nomem_imp_cnt;
                }
                else
                {
                    mem_imp[mem_imp_cnt] = grmem;
                    ++mem_imp_cnt;
                }
                break;
            case '@':
                if (neg)
                {
                    nomem_rec[nomem_rec_cnt] = grmem;
                    ++nomem_rec_cnt;
                }
                else
                {
                    mem_rec[mem_rec_cnt] = grmem;
                    ++mem_rec_cnt;
                }
                break;
            default:
                if (neg)
                {
                    nomem_exp[nomem_exp_cnt] = grmem;
                    ++nomem_exp_cnt;
                }
                else
                {
                    mem_exp[mem_exp_cnt] = grmem;
                    ++mem_exp_cnt;
                }
                break;
            }
        }
        {
            char buf[strlen (NIS_RES_OBJECT (res)->zo_domain) + 10];
            printf (_("Group entry for \"%s.%s\" group:\n"),
                    NIS_RES_OBJECT (res)->zo_name,
                    nis_domain_of_r (NIS_RES_OBJECT (res)->zo_domain,
                                     buf, strlen (NIS_RES_OBJECT (res)->zo_domain)
                                     + 10));
        }
        if (mem_exp_cnt)
        {
            fputs (_("    Explicit members:\n"), stdout);
            for (i = 0; i < mem_exp_cnt; ++i)
                printf ("\t%s\n", mem_exp[i]);
        }
        else
            fputs (_("    No explicit members\n"), stdout);
        if (mem_imp_cnt)
        {
            fputs (_("    Implicit members:\n"), stdout);
            for (i = 0; i < mem_imp_cnt; ++i)
                printf ("\t%s\n", &mem_imp[i][2]);
        }
        else
            fputs (_("    No implicit members\n"), stdout);
        if (mem_rec_cnt)
        {
            fputs (_("    Recursive members:\n"), stdout);
            for (i = 0; i < mem_rec_cnt; ++i)
                printf ("\t%s\n", &mem_rec[i][1]);
        }
        else
            fputs (_("    No recursive members\n"), stdout);
        if (nomem_exp_cnt)
        {
            fputs (_("    Explicit nonmembers:\n"), stdout);
            for (i = 0; i < nomem_exp_cnt; ++i)
                printf ("\t%s\n", &nomem_exp[i][1]);
        }
        else
            fputs (_("    No explicit nonmembers\n"), stdout);
        if (nomem_imp_cnt)
        {
            fputs (_("    Implicit nonmembers:\n"), stdout);
            for (i = 0; i < nomem_imp_cnt; ++i)
                printf ("\t%s\n", &nomem_imp[i][3]);
        }
        else
            fputs (_("    No implicit nonmembers\n"), stdout);
        if (nomem_rec_cnt)
        {
            fputs (_("    Recursive nonmembers:\n"), stdout);
            for (i = 0; i < nomem_rec_cnt; ++i)
                printf ("\t%s=n", &nomem_rec[i][2]);
        }
        else
            fputs (_("    No recursive nonmembers\n"), stdout);

        nis_freeresult (res);
    }
}
Example #6
0
/**
 * assuan_inquire:
 * @ctx: An assuan context
 * @keyword: The keyword used for the inquire
 * @r_buffer: Returns an allocated buffer
 * @r_length: Returns the length of this buffer
 * @maxlen: If not 0, the size limit of the inquired data.
 * 
 * A Server may use this to Send an inquire.  r_buffer, r_length and
 * maxlen may all be NULL/0 to indicate that no real data is expected.
 * 
 * Return value: 0 on success or an ASSUAN error code
 **/
gpg_error_t
assuan_inquire (assuan_context_t ctx, const char *keyword,
                unsigned char **r_buffer, size_t *r_length, size_t maxlen)
{
  gpg_error_t rc;
  struct membuf mb;
  char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */
  unsigned char *line, *p;
  int linelen;
  int nodataexpected;

  if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
  nodataexpected = !r_buffer && !r_length && !maxlen;
  if (!nodataexpected && (!r_buffer || !r_length))
    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
  if (!ctx->is_server)
    return _assuan_error (ctx, GPG_ERR_ASS_NOT_A_SERVER);
  if (ctx->in_inquire)
    return _assuan_error (ctx, GPG_ERR_ASS_NESTED_COMMANDS);
  
  ctx->in_inquire = 1;
  if (nodataexpected)
    memset (&mb, 0, sizeof mb); /* avoid compiler warnings */
  else
    init_membuf (ctx, &mb, maxlen? maxlen:1024, maxlen);

  strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
  rc = assuan_write_line (ctx, cmdbuf);
  if (rc)
    goto out;

  for (;;)
    {
      do 
        {
	  do
	    rc = _assuan_read_line (ctx);
	  while (_assuan_error_is_eagain (ctx, rc));
          if (rc)
            goto out;
          line = (unsigned char *) ctx->inbound.line;
          linelen = ctx->inbound.linelen;
        }    
      while (*line == '#' || !linelen);

      /* Note: As a convenience for manual testing we allow case
         insensitive keywords.  */
      if ((line[0] == 'E'||line[0] == 'e')
          && (line[1] == 'N' || line[1] == 'n')
          && (line[2] == 'D' || line[2] == 'd')
          && (!line[3] || line[3] == ' '))
        break; /* END command received*/
      if ((line[0] == 'C' || line[0] == 'c')
          && (line[1] == 'A' || line[1] == 'a')
          && (line[2] == 'N' || line[2] == 'n'))
        {
          rc = _assuan_error (ctx, GPG_ERR_ASS_CANCELED);
          goto out;
        }
      if ((line[0] != 'D' && line[0] != 'd') 
          || line[1] != ' ' || nodataexpected)
        {
          rc = _assuan_error (ctx, GPG_ERR_ASS_UNEXPECTED_CMD);
          goto out;
        }
      if (linelen < 3)
        continue;
      line += 2;
      linelen -= 2;

      p = line;
      while (linelen)
        {
          for (;linelen && *p != '%'; linelen--, p++)
            ;
          put_membuf (ctx, &mb, line, p-line);
          if (linelen > 2)
            { /* handle escaping */
              unsigned char tmp[1];
              p++;
              *tmp = xtoi_2 (p);
              p += 2;
              linelen -= 3;
              put_membuf (ctx, &mb, tmp, 1);
            }
          line = p;
        }
      if (mb.too_large)
        {
          rc = _assuan_error (ctx, GPG_ERR_ASS_TOO_MUCH_DATA);
          goto out;
        }
    }

  if (!nodataexpected)
    {
      *r_buffer = get_membuf (ctx, &mb, r_length);
      if (!*r_buffer)
	rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
    }

 out:
  if (!nodataexpected)
    free_membuf (ctx, &mb);
  ctx->in_inquire = 0;
  return rc;
}
Example #7
0
static int process_root_password(void) {

        static const char table[] =
                "abcdefghijklmnopqrstuvwxyz"
                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                "0123456789"
                "./";

        struct spwd item = {
                .sp_namp = (char*) "root",
                .sp_min = -1,
                .sp_max = -1,
                .sp_warn = -1,
                .sp_inact = -1,
                .sp_expire = -1,
                .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */
        };

        _cleanup_close_ int lock = -1;
        char salt[3+16+1+1];
        uint8_t raw[16];
        unsigned i;
        char *j;

        const char *etc_shadow;
        int r;

        etc_shadow = prefix_roota(arg_root, "/etc/shadow");
        if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
                return 0;

        mkdir_parents(etc_shadow, 0755);

        lock = take_password_lock(arg_root);
        if (lock < 0)
                return lock;

        if (arg_copy_root_password && arg_root) {
                struct spwd *p;

                errno = 0;
                p = getspnam("root");
                if (p || errno != ENOENT) {
                        if (!p) {
                                if (!errno)
                                        errno = EIO;

                                log_error_errno(errno, "Failed to find shadow entry for root: %m");
                                return -errno;
                        }

                        r = write_root_shadow(etc_shadow, p);
                        if (r < 0)
                                return log_error_errno(r, "Failed to write %s: %m", etc_shadow);

                        log_info("%s copied.", etc_shadow);
                        return 0;
                }
        }

        r = prompt_root_password();
        if (r < 0)
                return r;

        if (!arg_root_password)
                return 0;

        r = dev_urandom(raw, 16);
        if (r < 0)
                return log_error_errno(r, "Failed to get salt: %m");

        /* We only bother with SHA512 hashed passwords, the rest is legacy, and we don't do legacy. */
        assert_cc(sizeof(table) == 64 + 1);
        j = stpcpy(salt, "$6$");
        for (i = 0; i < 16; i++)
                j[i] = table[raw[i] & 63];
        j[i++] = '$';
        j[i] = 0;

        errno = 0;
        item.sp_pwdp = crypt(arg_root_password, salt);
        if (!item.sp_pwdp) {
                if (!errno)
                        errno = -EINVAL;

                log_error_errno(errno, "Failed to encrypt password: %m");
                return -errno;
        }

        item.sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);

        r = write_root_shadow(etc_shadow, &item);
        if (r < 0)
                return log_error_errno(r, "Failed to write %s: %m", etc_shadow);

        log_info("%s written.", etc_shadow);
        return 0;
}

static void help(void) {
        printf("%s [OPTIONS...]\n\n"
               "Configures basic settings of the system.\n\n"
               "  -h --help                    Show this help\n"
               "     --version                 Show package version\n"
               "     --root=PATH               Operate on an alternate filesystem root\n"
               "     --locale=LOCALE           Set primary locale (LANG=)\n"
               "     --locale-messages=LOCALE  Set message locale (LC_MESSAGES=)\n"
               "     --timezone=TIMEZONE       Set timezone\n"
               "     --hostname=NAME           Set host name\n"
               "     --machine-ID=ID           Set machine ID\n"
               "     --root-password=PASSWORD  Set root password\n"
               "     --root-password-file=FILE Set root password from file\n"
               "     --prompt-locale           Prompt the user for locale settings\n"
               "     --prompt-timezone         Prompt the user for timezone\n"
               "     --prompt-hostname         Prompt the user for hostname\n"
               "     --prompt-root-password    Prompt the user for root password\n"
               "     --prompt                  Prompt for all of the above\n"
               "     --copy-locale             Copy locale from host\n"
               "     --copy-timezone           Copy timezone from host\n"
               "     --copy-root-password      Copy root password from host\n"
               "     --copy                    Copy locale, timezone, root password\n"
               "     --setup-machine-id        Generate a new random machine ID\n"
               , program_invocation_short_name);
}
Example #8
0
File: cp.c Project: dennis95/dennix
int main(int argc, char* argv[]) {
    struct option longopts[] = {
        { "force", no_argument, 0, 'f' },
        { "interactive", no_argument, 0, 'i' },
        { "recursive", no_argument, 0, 'R' },
        { "help", no_argument, 0, 0 },
        { "version", no_argument, 0, 1 },
        { 0, 0, 0, 0 }
    };

    bool force = false;
    bool prompt = false;
    bool recursive = false;
    int c;
    while ((c = getopt_long(argc, argv, "fiRr", longopts, NULL)) != -1) {
        switch (c) {
        case 0:
            return help(argv[0], "[OPTIONS] SOURCE... DESTINATION\n"
                    "  -f, --force              force copy\n"
                    "  -i, --interactive        prompt before overwrite\n"
                    "  -R, -r, --recursive      recursively copy directories\n"
                    "      --help               display this help\n"
                    "      --version            display version info");
        case 1:
            return version(argv[0]);
        case 'f':
            force = true;
            prompt = false;
            break;
        case 'i':
            force = false;
            prompt = true;
            break;
        case 'r':
        case 'R':
            recursive = true;
            break;
        case '?':
            return 1;
        }
    }

    if (optind >= argc) errx(1, "missing source operand");
    if (optind == argc - 1) errx(1, "missing destination operand");

    const char* destination = argv[argc - 1];
    if (optind == argc - 2) {
        struct stat destSt;
        int statResult = stat(destination, &destSt);
        if (statResult < 0 && errno != ENOENT) {
            err(1, "stat: '%s'", destination);
        } else if ((statResult < 0 && errno == ENOENT) ||
                !S_ISDIR(destSt.st_mode)) {
            copy(AT_FDCWD, argv[optind], argv[optind], AT_FDCWD, destination,
                    destination, force, prompt, recursive);
            return status;
        }
    }

    int destFd = open(destination, O_SEARCH | O_DIRECTORY);
    if (destFd < 0) err(1, "open: '%s'", destination);
    for (int i = optind; i < argc - 1; i++) {
        const char* source = argv[i];
        char* sourceCopy = strdup(source);
        if (!sourceCopy) err(1, "strdup");
        char* destName = basename(sourceCopy);
        if (strcmp(destName, "/") == 0) {
            destName = ".";
        }
        char* destPath = malloc(strlen(destination) + strlen(destName) + 2);
        if (!destPath) err(1, "malloc");
        stpcpy(stpcpy(stpcpy(destPath, destination), "/"), destName);
        copy(AT_FDCWD, source, source, destFd, destName, destPath, force,
                prompt, recursive);
        free(sourceCopy);
        free(destPath);
    }
}
static int
do_test (void)
{
  struct sigaction sa;
  sa.sa_handler = handler;
  sa.sa_flags = 0;
  sigemptyset (&sa.sa_mask);

  sigaction (SIGABRT, &sa, NULL);

  /* Avoid all the buffer overflow messages on stderr.  */
  int fd = open (_PATH_DEVNULL, O_WRONLY);
  if (fd == -1)
    close (STDERR_FILENO);
  else
    {
      dup2 (fd, STDERR_FILENO);
      close (fd);
    }
  setenv ("LIBC_FATAL_STDERR_", "1", 1);

  struct A { char buf1[9]; char buf2[1]; } a;
  struct wA { wchar_t buf1[9]; wchar_t buf2[1]; } wa;

  printf ("Test checking routines at fortify level %d\n",
#ifdef __USE_FORTIFY_LEVEL
	  (int) __USE_FORTIFY_LEVEL
#else
	  0
#endif
	  );

  /* These ops can be done without runtime checking of object size.  */
  memcpy (buf, "abcdefghij", 10);
  memmove (buf + 1, buf, 9);
  if (memcmp (buf, "aabcdefghi", 10))
    FAIL ();

  if (mempcpy (buf + 5, "abcde", 5) != buf + 10
      || memcmp (buf, "aabcdabcde", 10))
    FAIL ();

  memset (buf + 8, 'j', 2);
  if (memcmp (buf, "aabcdabcjj", 10))
    FAIL ();

  strcpy (buf + 4, "EDCBA");
  if (memcmp (buf, "aabcEDCBA", 10))
    FAIL ();

  if (stpcpy (buf + 8, "F") != buf + 9 || memcmp (buf, "aabcEDCBF", 10))
    FAIL ();

  strncpy (buf + 6, "X", 4);
  if (memcmp (buf, "aabcEDX\0\0", 10))
    FAIL ();

  if (sprintf (buf + 7, "%s", "67") != 2 || memcmp (buf, "aabcEDX67", 10))
    FAIL ();

  if (snprintf (buf + 7, 3, "%s", "987654") != 6
      || memcmp (buf, "aabcEDX98", 10))
    FAIL ();

  /* These ops need runtime checking, but shouldn't __chk_fail.  */
  memcpy (buf, "abcdefghij", l0 + 10);
  memmove (buf + 1, buf, l0 + 9);
  if (memcmp (buf, "aabcdefghi", 10))
    FAIL ();

  if (mempcpy (buf + 5, "abcde", l0 + 5) != buf + 10
      || memcmp (buf, "aabcdabcde", 10))
    FAIL ();

  memset (buf + 8, 'j', l0 + 2);
  if (memcmp (buf, "aabcdabcjj", 10))
    FAIL ();

  strcpy (buf + 4, str1 + 5);
  if (memcmp (buf, "aabcEDCBA", 10))
    FAIL ();

  if (stpcpy (buf + 8, str2) != buf + 9 || memcmp (buf, "aabcEDCBF", 10))
    FAIL ();

  strncpy (buf + 6, "X", l0 + 4);
  if (memcmp (buf, "aabcEDX\0\0", 10))
    FAIL ();

  if (stpncpy (buf + 5, "cd", l0 + 5) != buf + 7
      || memcmp (buf, "aabcEcd\0\0", 10))
    FAIL ();

  if (sprintf (buf + 7, "%d", num1) != 2 || memcmp (buf, "aabcEcd67", 10))
    FAIL ();

  if (snprintf (buf + 7, 3, "%d", num2) != 6 || memcmp (buf, "aabcEcd98", 10))
    FAIL ();

  buf[l0 + 8] = '\0';
  strcat (buf, "A");
  if (memcmp (buf, "aabcEcd9A", 10))
    FAIL ();

  buf[l0 + 7] = '\0';
  strncat (buf, "ZYXWV", l0 + 2);
  if (memcmp (buf, "aabcEcdZY", 10))
    FAIL ();

  memcpy (a.buf1, "abcdefghij", l0 + 10);
  memmove (a.buf1 + 1, a.buf1, l0 + 9);
  if (memcmp (a.buf1, "aabcdefghi", 10))
    FAIL ();

  if (mempcpy (a.buf1 + 5, "abcde", l0 + 5) != a.buf1 + 10
      || memcmp (a.buf1, "aabcdabcde", 10))
    FAIL ();

  memset (a.buf1 + 8, 'j', l0 + 2);
  if (memcmp (a.buf1, "aabcdabcjj", 10))
    FAIL ();

#if __USE_FORTIFY_LEVEL < 2
  /* The following tests are supposed to crash with -D_FORTIFY_SOURCE=2
     and sufficient GCC support, as the string operations overflow
     from a.buf1 into a.buf2.  */
  strcpy (a.buf1 + 4, str1 + 5);
  if (memcmp (a.buf1, "aabcEDCBA", 10))
    FAIL ();

  if (stpcpy (a.buf1 + 8, str2) != a.buf1 + 9
      || memcmp (a.buf1, "aabcEDCBF", 10))
    FAIL ();

  strncpy (a.buf1 + 6, "X", l0 + 4);
  if (memcmp (a.buf1, "aabcEDX\0\0", 10))
    FAIL ();

  if (sprintf (a.buf1 + 7, "%d", num1) != 2
      || memcmp (a.buf1, "aabcEDX67", 10))
    FAIL ();

  if (snprintf (a.buf1 + 7, 3, "%d", num2) != 6
      || memcmp (a.buf1, "aabcEDX98", 10))
    FAIL ();

  a.buf1[l0 + 8] = '\0';
  strcat (a.buf1, "A");
  if (memcmp (a.buf1, "aabcEDX9A", 10))
    FAIL ();

  a.buf1[l0 + 7] = '\0';
  strncat (a.buf1, "ZYXWV", l0 + 2);
  if (memcmp (a.buf1, "aabcEDXZY", 10))
    FAIL ();

#endif

#if __USE_FORTIFY_LEVEL >= 1
  /* Now check if all buffer overflows are caught at runtime.  */

  CHK_FAIL_START
  memcpy (buf + 1, "abcdefghij", l0 + 10);
  CHK_FAIL_END

  CHK_FAIL_START
  memmove (buf + 2, buf + 1, l0 + 9);
  CHK_FAIL_END

  CHK_FAIL_START
  p = mempcpy (buf + 6, "abcde", l0 + 5);
  CHK_FAIL_END

  CHK_FAIL_START
  memset (buf + 9, 'j', l0 + 2);
  CHK_FAIL_END

  CHK_FAIL_START
  strcpy (buf + 5, str1 + 5);
  CHK_FAIL_END

  CHK_FAIL_START
  p = stpcpy (buf + 9, str2);
  CHK_FAIL_END

  CHK_FAIL_START
  strncpy (buf + 7, "X", l0 + 4);
  CHK_FAIL_END

  CHK_FAIL_START
  stpncpy (buf + 6, "cd", l0 + 5);
  CHK_FAIL_END

  CHK_FAIL_START
  sprintf (buf + 8, "%d", num1);
  CHK_FAIL_END

  CHK_FAIL_START
  snprintf (buf + 8, l0 + 3, "%d", num2);
  CHK_FAIL_END

  memcpy (buf, str1 + 2, l0 + 9);
  CHK_FAIL_START
  strcat (buf, "AB");
  CHK_FAIL_END

  memcpy (buf, str1 + 3, l0 + 8);
  CHK_FAIL_START
  strncat (buf, "ZYXWV", l0 + 3);
  CHK_FAIL_END

  CHK_FAIL_START
  memcpy (a.buf1 + 1, "abcdefghij", l0 + 10);
  CHK_FAIL_END

  CHK_FAIL_START
  memmove (a.buf1 + 2, a.buf1 + 1, l0 + 9);
  CHK_FAIL_END

  CHK_FAIL_START
  p = mempcpy (a.buf1 + 6, "abcde", l0 + 5);
  CHK_FAIL_END

  CHK_FAIL_START
  memset (a.buf1 + 9, 'j', l0 + 2);
  CHK_FAIL_END

#if __USE_FORTIFY_LEVEL >= 2
# define O 0
#else
# define O 1
#endif

  CHK_FAIL_START
  strcpy (a.buf1 + (O + 4), str1 + 5);
  CHK_FAIL_END

  CHK_FAIL_START
  p = stpcpy (a.buf1 + (O + 8), str2);
  CHK_FAIL_END

  CHK_FAIL_START
  strncpy (a.buf1 + (O + 6), "X", l0 + 4);
  CHK_FAIL_END

  CHK_FAIL_START
  sprintf (a.buf1 + (O + 7), "%d", num1);
  CHK_FAIL_END

  CHK_FAIL_START
  snprintf (a.buf1 + (O + 7), l0 + 3, "%d", num2);
  CHK_FAIL_END

  memcpy (a.buf1, str1 + (3 - O), l0 + 8 + O);
  CHK_FAIL_START
  strcat (a.buf1, "AB");
  CHK_FAIL_END

  memcpy (a.buf1, str1 + (4 - O), l0 + 7 + O);
  CHK_FAIL_START
  strncat (a.buf1, "ZYXWV", l0 + 3);
  CHK_FAIL_END
#endif


  /* These ops can be done without runtime checking of object size.  */
  wmemcpy (wbuf, L"abcdefghij", 10);
  wmemmove (wbuf + 1, wbuf, 9);
  if (wmemcmp (wbuf, L"aabcdefghi", 10))
    FAIL ();

  if (wmempcpy (wbuf + 5, L"abcde", 5) != wbuf + 10
      || wmemcmp (wbuf, L"aabcdabcde", 10))
    FAIL ();

  wmemset (wbuf + 8, L'j', 2);
  if (wmemcmp (wbuf, L"aabcdabcjj", 10))
    FAIL ();

  wcscpy (wbuf + 4, L"EDCBA");
  if (wmemcmp (wbuf, L"aabcEDCBA", 10))
    FAIL ();

  if (wcpcpy (wbuf + 8, L"F") != wbuf + 9 || wmemcmp (wbuf, L"aabcEDCBF", 10))
    FAIL ();

  wcsncpy (wbuf + 6, L"X", 4);
  if (wmemcmp (wbuf, L"aabcEDX\0\0", 10))
    FAIL ();

  if (swprintf (wbuf + 7, 3, L"%ls", L"987654") >= 0
      || wmemcmp (wbuf, L"aabcEDX98", 10))
    FAIL ();

  if (swprintf (wbuf + 7, 3, L"64") != 2
      || wmemcmp (wbuf, L"aabcEDX64", 10))
    FAIL ();

  /* These ops need runtime checking, but shouldn't __chk_fail.  */
  wmemcpy (wbuf, L"abcdefghij", l0 + 10);
  wmemmove (wbuf + 1, wbuf, l0 + 9);
  if (wmemcmp (wbuf, L"aabcdefghi", 10))
    FAIL ();

  if (wmempcpy (wbuf + 5, L"abcde", l0 + 5) != wbuf + 10
      || wmemcmp (wbuf, L"aabcdabcde", 10))
    FAIL ();

  wmemset (wbuf + 8, L'j', l0 + 2);
  if (wmemcmp (wbuf, L"aabcdabcjj", 10))
    FAIL ();

  wcscpy (wbuf + 4, wstr1 + 5);
  if (wmemcmp (wbuf, L"aabcEDCBA", 10))
    FAIL ();

  if (wcpcpy (wbuf + 8, wstr2) != wbuf + 9 || wmemcmp (wbuf, L"aabcEDCBF", 10))
    FAIL ();

  wcsncpy (wbuf + 6, L"X", l0 + 4);
  if (wmemcmp (wbuf, L"aabcEDX\0\0", 10))
    FAIL ();

  if (wcpncpy (wbuf + 5, L"cd", l0 + 5) != wbuf + 7
      || wmemcmp (wbuf, L"aabcEcd\0\0", 10))
    FAIL ();

  if (swprintf (wbuf + 7, 3, L"%d", num2) >= 0
      || wmemcmp (wbuf, L"aabcEcd98", 10))
    FAIL ();

  wbuf[l0 + 8] = L'\0';
  wcscat (wbuf, L"A");
  if (wmemcmp (wbuf, L"aabcEcd9A", 10))
    FAIL ();

  wbuf[l0 + 7] = L'\0';
  wcsncat (wbuf, L"ZYXWV", l0 + 2);
  if (wmemcmp (wbuf, L"aabcEcdZY", 10))
    FAIL ();

  wmemcpy (wa.buf1, L"abcdefghij", l0 + 10);
  wmemmove (wa.buf1 + 1, wa.buf1, l0 + 9);
  if (wmemcmp (wa.buf1, L"aabcdefghi", 10))
    FAIL ();

  if (wmempcpy (wa.buf1 + 5, L"abcde", l0 + 5) != wa.buf1 + 10
      || wmemcmp (wa.buf1, L"aabcdabcde", 10))
    FAIL ();

  wmemset (wa.buf1 + 8, L'j', l0 + 2);
  if (wmemcmp (wa.buf1, L"aabcdabcjj", 10))
    FAIL ();

#if __USE_FORTIFY_LEVEL < 2
  /* The following tests are supposed to crash with -D_FORTIFY_SOURCE=2
     and sufficient GCC support, as the string operations overflow
     from a.buf1 into a.buf2.  */
  wcscpy (wa.buf1 + 4, wstr1 + 5);
  if (wmemcmp (wa.buf1, L"aabcEDCBA", 10))
    FAIL ();

  if (wcpcpy (wa.buf1 + 8, wstr2) != wa.buf1 + 9
      || wmemcmp (wa.buf1, L"aabcEDCBF", 10))
    FAIL ();

  wcsncpy (wa.buf1 + 6, L"X", l0 + 4);
  if (wmemcmp (wa.buf1, L"aabcEDX\0\0", 10))
    FAIL ();

  if (swprintf (wa.buf1 + 7, 3, L"%d", num2) >= 0
      || wmemcmp (wa.buf1, L"aabcEDX98", 10))
    FAIL ();

  wa.buf1[l0 + 8] = L'\0';
  wcscat (wa.buf1, L"A");
  if (wmemcmp (wa.buf1, L"aabcEDX9A", 10))
    FAIL ();

  wa.buf1[l0 + 7] = L'\0';
  wcsncat (wa.buf1, L"ZYXWV", l0 + 2);
  if (wmemcmp (wa.buf1, L"aabcEDXZY", 10))
    FAIL ();

#endif

#if __USE_FORTIFY_LEVEL >= 1
  /* Now check if all buffer overflows are caught at runtime.  */

  CHK_FAIL_START
  wmemcpy (wbuf + 1, L"abcdefghij", l0 + 10);
  CHK_FAIL_END

  CHK_FAIL_START
  wmemmove (wbuf + 2, wbuf + 1, l0 + 9);
  CHK_FAIL_END

  CHK_FAIL_START
    wp = wmempcpy (wbuf + 6, L"abcde", l0 + 5);
  CHK_FAIL_END

  CHK_FAIL_START
  wmemset (wbuf + 9, L'j', l0 + 2);
  CHK_FAIL_END

  CHK_FAIL_START
  wcscpy (wbuf + 5, wstr1 + 5);
  CHK_FAIL_END

  CHK_FAIL_START
  wp = wcpcpy (wbuf + 9, wstr2);
  CHK_FAIL_END

  CHK_FAIL_START
  wcsncpy (wbuf + 7, L"X", l0 + 4);
  CHK_FAIL_END

  CHK_FAIL_START
  wcpncpy (wbuf + 6, L"cd", l0 + 5);
  CHK_FAIL_END

  wmemcpy (wbuf, wstr1 + 2, l0 + 9);
  CHK_FAIL_START
  wcscat (wbuf, L"AB");
  CHK_FAIL_END

  wmemcpy (wbuf, wstr1 + 3, l0 + 8);
  CHK_FAIL_START
  wcsncat (wbuf, L"ZYXWV", l0 + 3);
  CHK_FAIL_END

  CHK_FAIL_START
  wmemcpy (wa.buf1 + 1, L"abcdefghij", l0 + 10);
  CHK_FAIL_END

  CHK_FAIL_START
  wmemmove (wa.buf1 + 2, wa.buf1 + 1, l0 + 9);
  CHK_FAIL_END

  CHK_FAIL_START
  wp = wmempcpy (wa.buf1 + 6, L"abcde", l0 + 5);
  CHK_FAIL_END

  CHK_FAIL_START
  wmemset (wa.buf1 + 9, L'j', l0 + 2);
  CHK_FAIL_END

#if __USE_FORTIFY_LEVEL >= 2
# define O 0
#else
# define O 1
#endif

  CHK_FAIL_START
  wcscpy (wa.buf1 + (O + 4), wstr1 + 5);
  CHK_FAIL_END

  CHK_FAIL_START
  wp = wcpcpy (wa.buf1 + (O + 8), wstr2);
  CHK_FAIL_END

  CHK_FAIL_START
  wcsncpy (wa.buf1 + (O + 6), L"X", l0 + 4);
  CHK_FAIL_END

  wmemcpy (wa.buf1, wstr1 + (3 - O), l0 + 8 + O);
  CHK_FAIL_START
  wcscat (wa.buf1, L"AB");
  CHK_FAIL_END

  wmemcpy (wa.buf1, wstr1 + (4 - O), l0 + 7 + O);
  CHK_FAIL_START
  wcsncat (wa.buf1, L"ZYXWV", l0 + 3);
  CHK_FAIL_END
#endif


  /* Now checks for %n protection.  */

  /* Constant literals passed directly are always ok
     (even with warnings about possible bugs from GCC).  */
  int n1, n2;
  if (sprintf (buf, "%s%n%s%n", str2, &n1, str2, &n2) != 2
      || n1 != 1 || n2 != 2)
    FAIL ();

  /* In this case the format string is not known at compile time,
     but resides in read-only memory, so is ok.  */
  if (snprintf (buf, 4, str3, str2, &n1, str2, &n2) != 2
      || n1 != 1 || n2 != 2)
    FAIL ();

  strcpy (buf2 + 2, "%n%s%n");
  /* When the format string is writable and contains %n,
     with -D_FORTIFY_SOURCE=2 it causes __chk_fail.  */
  CHK_FAIL2_START
  if (sprintf (buf, buf2, str2, &n1, str2, &n1) != 2)
    FAIL ();
  CHK_FAIL2_END

  CHK_FAIL2_START
  if (snprintf (buf, 3, buf2, str2, &n1, str2, &n1) != 2)
    FAIL ();
  CHK_FAIL2_END

  /* But if there is no %n, even writable format string
     should work.  */
  buf2[6] = '\0';
  if (sprintf (buf, buf2 + 4, str2) != 1)
    FAIL ();

  /* Constant literals passed directly are always ok
     (even with warnings about possible bugs from GCC).  */
  if (printf ("%s%n%s%n", str4, &n1, str5, &n2) != 14
      || n1 != 7 || n2 != 14)
    FAIL ();

  /* In this case the format string is not known at compile time,
     but resides in read-only memory, so is ok.  */
  if (printf (str3, str4, &n1, str5, &n2) != 14
      || n1 != 7 || n2 != 14)
    FAIL ();

  strcpy (buf2 + 2, "%n%s%n");
  /* When the format string is writable and contains %n,
     with -D_FORTIFY_SOURCE=2 it causes __chk_fail.  */
  CHK_FAIL2_START
  if (printf (buf2, str4, &n1, str5, &n1) != 14)
    FAIL ();
  CHK_FAIL2_END

  /* But if there is no %n, even writable format string
     should work.  */
  buf2[6] = '\0';
  if (printf (buf2 + 4, str5) != 7)
    FAIL ();

  FILE *fp = stdout;

  /* Constant literals passed directly are always ok
     (even with warnings about possible bugs from GCC).  */
  if (fprintf (fp, "%s%n%s%n", str4, &n1, str5, &n2) != 14
      || n1 != 7 || n2 != 14)
    FAIL ();

  /* In this case the format string is not known at compile time,
     but resides in read-only memory, so is ok.  */
  if (fprintf (fp, str3, str4, &n1, str5, &n2) != 14
      || n1 != 7 || n2 != 14)
    FAIL ();

  strcpy (buf2 + 2, "%n%s%n");
  /* When the format string is writable and contains %n,
     with -D_FORTIFY_SOURCE=2 it causes __chk_fail.  */
  CHK_FAIL2_START
  if (fprintf (fp, buf2, str4, &n1, str5, &n1) != 14)
    FAIL ();
  CHK_FAIL2_END

  /* But if there is no %n, even writable format string
     should work.  */
  buf2[6] = '\0';
  if (fprintf (fp, buf2 + 4, str5) != 7)
    FAIL ();

  if (freopen (temp_filename, "r", stdin) == NULL)
    {
      puts ("could not open temporary file");
      exit (1);
    }

  if (gets (buf) != buf || memcmp (buf, "abcdefgh", 9))
    FAIL ();
  if (gets (buf) != buf || memcmp (buf, "ABCDEFGHI", 10))
    FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
  CHK_FAIL_START
  if (gets (buf) != buf)
    FAIL ();
  CHK_FAIL_END
#endif

  rewind (stdin);

  if (fgets (buf, sizeof (buf), stdin) != buf
      || memcmp (buf, "abcdefgh\n", 10))
    FAIL ();
  if (fgets (buf, sizeof (buf), stdin) != buf || memcmp (buf, "ABCDEFGHI", 10))
    FAIL ();

  rewind (stdin);

  if (fgets (buf, l0 + sizeof (buf), stdin) != buf
      || memcmp (buf, "abcdefgh\n", 10))
    FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
  CHK_FAIL_START
  if (fgets (buf, sizeof (buf) + 1, stdin) != buf)
    FAIL ();
  CHK_FAIL_END

  CHK_FAIL_START
  if (fgets (buf, l0 + sizeof (buf) + 1, stdin) != buf)
    FAIL ();
  CHK_FAIL_END
#endif

  rewind (stdin);

  if (fgets_unlocked (buf, sizeof (buf), stdin) != buf
      || memcmp (buf, "abcdefgh\n", 10))
    FAIL ();
  if (fgets_unlocked (buf, sizeof (buf), stdin) != buf
      || memcmp (buf, "ABCDEFGHI", 10))
    FAIL ();

  rewind (stdin);

  if (fgets_unlocked (buf, l0 + sizeof (buf), stdin) != buf
      || memcmp (buf, "abcdefgh\n", 10))
    FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
  CHK_FAIL_START
  if (fgets_unlocked (buf, sizeof (buf) + 1, stdin) != buf)
    FAIL ();
  CHK_FAIL_END

  CHK_FAIL_START
  if (fgets_unlocked (buf, l0 + sizeof (buf) + 1, stdin) != buf)
    FAIL ();
  CHK_FAIL_END
#endif

  lseek (fileno (stdin), 0, SEEK_SET);

  if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1
      || memcmp (buf, "abcdefgh\n", 9))
    FAIL ();
  if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1
      || memcmp (buf, "ABCDEFGHI", 9))
    FAIL ();

  lseek (fileno (stdin), 0, SEEK_SET);

  if (read (fileno (stdin), buf, l0 + sizeof (buf) - 1) != sizeof (buf) - 1
      || memcmp (buf, "abcdefgh\n", 9))
    FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
  CHK_FAIL_START
  if (read (fileno (stdin), buf, sizeof (buf) + 1) != sizeof (buf) + 1)
    FAIL ();
  CHK_FAIL_END
#endif

  if (pread (fileno (stdin), buf, sizeof (buf) - 1, sizeof (buf) - 2)
      != sizeof (buf) - 1
      || memcmp (buf, "\nABCDEFGH", 9))
    FAIL ();
  if (pread (fileno (stdin), buf, sizeof (buf) - 1, 0) != sizeof (buf) - 1
      || memcmp (buf, "abcdefgh\n", 9))
    FAIL ();
  if (pread (fileno (stdin), buf, l0 + sizeof (buf) - 1, sizeof (buf) - 3)
      != sizeof (buf) - 1
      || memcmp (buf, "h\nABCDEFG", 9))
    FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
  CHK_FAIL_START
  if (pread (fileno (stdin), buf, sizeof (buf) + 1, 2 * sizeof (buf))
      != sizeof (buf) + 1)
    FAIL ();
  CHK_FAIL_END
#endif

  if (pread64 (fileno (stdin), buf, sizeof (buf) - 1, sizeof (buf) - 2)
      != sizeof (buf) - 1
      || memcmp (buf, "\nABCDEFGH", 9))
    FAIL ();
  if (pread64 (fileno (stdin), buf, sizeof (buf) - 1, 0) != sizeof (buf) - 1
      || memcmp (buf, "abcdefgh\n", 9))
    FAIL ();
  if (pread64 (fileno (stdin), buf, l0 + sizeof (buf) - 1, sizeof (buf) - 3)
      != sizeof (buf) - 1
      || memcmp (buf, "h\nABCDEFG", 9))
    FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
  CHK_FAIL_START
  if (pread64 (fileno (stdin), buf, sizeof (buf) + 1, 2 * sizeof (buf))
      != sizeof (buf) + 1)
    FAIL ();
  CHK_FAIL_END
#endif

  if (freopen (temp_filename, "r", stdin) == NULL)
    {
      puts ("could not open temporary file");
      exit (1);
    }

  if (fseek (stdin, 9 + 10 + 11, SEEK_SET))
    {
      puts ("could not seek in test file");
      exit (1);
    }

#if __USE_FORTIFY_LEVEL >= 1
  CHK_FAIL_START
  if (gets (buf) != buf)
    FAIL ();
  CHK_FAIL_END
#endif

  /* Check whether missing N$ formats are detected.  */
  CHK_FAIL2_START
  printf ("%3$d\n", 1, 2, 3, 4);
  CHK_FAIL2_END

  CHK_FAIL2_START
  fprintf (stdout, "%3$d\n", 1, 2, 3, 4);
  CHK_FAIL2_END

  CHK_FAIL2_START
  sprintf (buf, "%3$d\n", 1, 2, 3, 4);
  CHK_FAIL2_END

  CHK_FAIL2_START
  snprintf (buf, sizeof (buf), "%3$d\n", 1, 2, 3, 4);
  CHK_FAIL2_END

  int sp[2];
  if (socketpair (PF_UNIX, SOCK_STREAM, 0, sp))
    FAIL ();
  else
    {
      const char *sendstr = "abcdefgh\nABCDEFGH\n0123456789\n";
      if (send (sp[0], sendstr, strlen (sendstr), 0) != strlen (sendstr))
	FAIL ();

      char recvbuf[12];
      if (recv (sp[1], recvbuf, sizeof recvbuf, MSG_PEEK)
	  != sizeof recvbuf
	  || memcmp (recvbuf, sendstr, sizeof recvbuf) != 0)
	FAIL ();

      if (recv (sp[1], recvbuf + 6, l0 + sizeof recvbuf - 7, MSG_PEEK)
	  != sizeof recvbuf - 7
	  || memcmp (recvbuf + 6, sendstr, sizeof recvbuf - 7) != 0)
	FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
      CHK_FAIL_START
      if (recv (sp[1], recvbuf + 1, sizeof recvbuf, MSG_PEEK)
	  != sizeof recvbuf)
	FAIL ();
      CHK_FAIL_END

      CHK_FAIL_START
      if (recv (sp[1], recvbuf + 4, l0 + sizeof recvbuf - 3, MSG_PEEK)
	  != sizeof recvbuf - 3)
	FAIL ();
      CHK_FAIL_END
#endif

      socklen_t sl;
      struct sockaddr_un sa_un;

      sl = sizeof (sa_un);
      if (recvfrom (sp[1], recvbuf, sizeof recvbuf, MSG_PEEK, &sa_un, &sl)
	  != sizeof recvbuf
	  || memcmp (recvbuf, sendstr, sizeof recvbuf) != 0)
	FAIL ();

      sl = sizeof (sa_un);
      if (recvfrom (sp[1], recvbuf + 6, l0 + sizeof recvbuf - 7, MSG_PEEK,
	  &sa_un, &sl) != sizeof recvbuf - 7
	  || memcmp (recvbuf + 6, sendstr, sizeof recvbuf - 7) != 0)
	FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
      CHK_FAIL_START
      sl = sizeof (sa_un);
      if (recvfrom (sp[1], recvbuf + 1, sizeof recvbuf, MSG_PEEK, &sa_un, &sl)
	  != sizeof recvbuf)
	FAIL ();
      CHK_FAIL_END

      CHK_FAIL_START
      sl = sizeof (sa_un);
      if (recvfrom (sp[1], recvbuf + 4, l0 + sizeof recvbuf - 3, MSG_PEEK,
	  &sa_un, &sl) != sizeof recvbuf - 3)
	FAIL ();
      CHK_FAIL_END
#endif

      close (sp[0]);
      close (sp[1]);
    }

  char fname[] = "/tmp/tst-chk1-dir-XXXXXX\0foo";
  char *enddir = strchr (fname, '\0');
  if (mkdtemp (fname) == NULL)
    {
      printf ("mkdtemp failed: %m\n");
      return 1;
    }
  *enddir = '/';
  if (symlink ("bar", fname) != 0)
    FAIL ();

  char readlinkbuf[4];
  if (readlink (fname, readlinkbuf, 4) != 3
      || memcmp (readlinkbuf, "bar", 3) != 0)
    FAIL ();
  if (readlink (fname, readlinkbuf + 1, l0 + 3) != 3
      || memcmp (readlinkbuf, "bbar", 4) != 0)
    FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
  CHK_FAIL_START
  if (readlink (fname, readlinkbuf + 2, l0 + 3) != 3)
    FAIL ();
  CHK_FAIL_END

  CHK_FAIL_START
  if (readlink (fname, readlinkbuf + 3, 4) != 3)
    FAIL ();
  CHK_FAIL_END
#endif

  char *cwd1 = getcwd (NULL, 0);
  if (cwd1 == NULL)
    FAIL ();

  char *cwd2 = getcwd (NULL, 250);
  if (cwd2 == NULL)
    FAIL ();

  if (cwd1 && cwd2)
    {
      if (strcmp (cwd1, cwd2) != 0)
	FAIL ();

      *enddir = '\0';
      if (chdir (fname))
	FAIL ();

      char *cwd3 = getcwd (NULL, 0);
      if (cwd3 == NULL)
	FAIL ();
      if (strcmp (fname, cwd3) != 0)
	printf ("getcwd after chdir is '%s' != '%s',"
		"get{c,}wd tests skipped\n", cwd3, fname);
      else
	{
	  char getcwdbuf[sizeof fname - 3];

	  char *cwd4 = getcwd (getcwdbuf, sizeof getcwdbuf);
	  if (cwd4 != getcwdbuf
	      || strcmp (getcwdbuf, fname) != 0)
	    FAIL ();

	  cwd4 = getcwd (getcwdbuf + 1, l0 + sizeof getcwdbuf - 1);
	  if (cwd4 != getcwdbuf + 1
	      || getcwdbuf[0] != fname[0]
	      || strcmp (getcwdbuf + 1, fname) != 0)
	    FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
	  CHK_FAIL_START
	  if (getcwd (getcwdbuf + 2, l0 + sizeof getcwdbuf)
	      != getcwdbuf + 2)
	    FAIL ();
	  CHK_FAIL_END

	  CHK_FAIL_START
	  if (getcwd (getcwdbuf + 2, sizeof getcwdbuf)
	      != getcwdbuf + 2)
	    FAIL ();
	  CHK_FAIL_END
#endif

	  if (getwd (getcwdbuf) != getcwdbuf
	      || strcmp (getcwdbuf, fname) != 0)
	    FAIL ();

	  if (getwd (getcwdbuf + 1) != getcwdbuf + 1
	      || strcmp (getcwdbuf + 1, fname) != 0)
	    FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
	  CHK_FAIL_START
	  if (getwd (getcwdbuf + 2) != getcwdbuf + 2)
	    FAIL ();
	  CHK_FAIL_END
#endif
	}

      if (chdir (cwd1) != 0)
	FAIL ();
      free (cwd3);
    }

  free (cwd1);
  free (cwd2);
  *enddir = '/';
  if (unlink (fname) != 0)
    FAIL ();

  *enddir = '\0';
  if (rmdir (fname) != 0)
    FAIL ();


#if PATH_MAX > 0
  char largebuf[PATH_MAX];
  char *realres = realpath (".", largebuf);
  if (realres != largebuf)
    FAIL ();

# if __USE_FORTIFY_LEVEL >= 1
  CHK_FAIL_START
  char realbuf[1];
  realres = realpath (".", realbuf);
  if (realres != realbuf)
    FAIL ();
  CHK_FAIL_END
# endif
#endif

  if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL)
    {
      assert (MB_CUR_MAX <= 10);

      /* First a simple test.  */
      char enough[10];
      if (wctomb (enough, L'A') != 1)
	FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
      /* We know the wchar_t encoding is ISO 10646.  So pick a
	 character which has a multibyte representation which does not
	 fit.  */
      CHK_FAIL_START
      char smallbuf[2];
      if (wctomb (smallbuf, L'\x100') != 2)
	FAIL ();
      CHK_FAIL_END
#endif

      mbstate_t s;
      memset (&s, '\0', sizeof (s));
      if (wcrtomb (enough, L'D', &s) != 1 || enough[0] != 'D')
	FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
      /* We know the wchar_t encoding is ISO 10646.  So pick a
	 character which has a multibyte representation which does not
	 fit.  */
      CHK_FAIL_START
      char smallbuf[2];
      if (wcrtomb (smallbuf, L'\x100', &s) != 2)
	FAIL ();
      CHK_FAIL_END
#endif

      wchar_t wenough[10];
      memset (&s, '\0', sizeof (s));
      const char *cp = "A";
      if (mbsrtowcs (wenough, &cp, 10, &s) != 1
	  || wcscmp (wenough, L"A") != 0)
	FAIL ();

      cp = "BC";
      if (mbsrtowcs (wenough, &cp, l0 + 10, &s) != 2
	  || wcscmp (wenough, L"BC") != 0)
	FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
      CHK_FAIL_START
      wchar_t wsmallbuf[2];
      cp = "ABC";
      mbsrtowcs (wsmallbuf, &cp, 10, &s);
      CHK_FAIL_END
#endif

      cp = "A";
      if (mbstowcs (wenough, cp, 10) != 1
	  || wcscmp (wenough, L"A") != 0)
	FAIL ();

      cp = "DEF";
      if (mbstowcs (wenough, cp, l0 + 10) != 3
	  || wcscmp (wenough, L"DEF") != 0)
	FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
      CHK_FAIL_START
      wchar_t wsmallbuf[2];
      cp = "ABC";
      mbstowcs (wsmallbuf, cp, 10);
      CHK_FAIL_END
#endif

      memset (&s, '\0', sizeof (s));
      cp = "ABC";
      wcscpy (wenough, L"DEF");
      if (mbsnrtowcs (wenough, &cp, 1, 10, &s) != 1
	  || wcscmp (wenough, L"AEF") != 0)
	FAIL ();

      cp = "IJ";
      if (mbsnrtowcs (wenough, &cp, 1, l0 + 10, &s) != 1
	  || wcscmp (wenough, L"IEF") != 0)
	FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
      CHK_FAIL_START
      wchar_t wsmallbuf[2];
      cp = "ABC";
      mbsnrtowcs (wsmallbuf, &cp, 3, 10, &s);
      CHK_FAIL_END
#endif

      memset (&s, '\0', sizeof (s));
      const wchar_t *wcp = L"A";
      if (wcsrtombs (enough, &wcp, 10, &s) != 1
	  || strcmp (enough, "A") != 0)
	FAIL ();

      wcp = L"BC";
      if (wcsrtombs (enough, &wcp, l0 + 10, &s) != 2
	  || strcmp (enough, "BC") != 0)
	FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
      CHK_FAIL_START
      char smallbuf[2];
      wcp = L"ABC";
      wcsrtombs (smallbuf, &wcp, 10, &s);
      CHK_FAIL_END
#endif

      memset (enough, 'Z', sizeof (enough));
      wcp = L"EF";
      if (wcstombs (enough, wcp, 10) != 2
	  || strcmp (enough, "EF") != 0)
	FAIL ();

      wcp = L"G";
      if (wcstombs (enough, wcp, l0 + 10) != 1
	  || strcmp (enough, "G") != 0)
	FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
      CHK_FAIL_START
      char smallbuf[2];
      wcp = L"ABC";
      wcstombs (smallbuf, wcp, 10);
      CHK_FAIL_END
#endif

      memset (&s, '\0', sizeof (s));
      wcp = L"AB";
      if (wcsnrtombs (enough, &wcp, 1, 10, &s) != 1
	  || strcmp (enough, "A") != 0)
	FAIL ();

      wcp = L"BCD";
      if (wcsnrtombs (enough, &wcp, 1, l0 + 10, &s) != 1
	  || strcmp (enough, "B") != 0)
	FAIL ();

#if __USE_FORTIFY_LEVEL >= 1
      CHK_FAIL_START
      char smallbuf[2];
      wcp = L"ABC";
      wcsnrtombs (smallbuf, &wcp, 3, 10, &s);
      CHK_FAIL_END
#endif
    }
Example #10
0
/**
 * Display help text for an option.
 * @param fp		output file handle
 * @param columns	output display width control
 * @param opt		option(s)
 * @param translation_domain	translation domain
 */
static void singleOptionHelp(FILE * fp, columns_t columns,
		const struct poptOption * opt,
		/*@null@*/ const char * translation_domain)
	/*@globals fileSystem @*/
	/*@modifies fp, fileSystem @*/
{
    size_t maxLeftCol = columns->cur;
    size_t indentLength = maxLeftCol + 5;
    size_t lineLength = columns->max - indentLength;
    const char * help = D_(translation_domain, opt->descrip);
    const char * argDescrip = getArgDescrip(opt, translation_domain);
    /* Display shortName iff printable non-space. */
    int prtshort = (int)(isprint((int)opt->shortName) && opt->shortName != ' ');
    size_t helpLength;
    char * defs = NULL;
    char * left;
    size_t nb = maxLeftCol + 1;
    int displaypad = 0;

    /* Make sure there's more than enough room in target buffer. */
    if (opt->longName)	nb += strlen(opt->longName);
    if (F_ISSET(opt, TOGGLE)) nb += sizeof("[no]") - 1;
    if (argDescrip)	nb += strlen(argDescrip);

    left = (char*) xmalloc(nb);
assert(left);	/* XXX can't happen */
    if (left == NULL) return;
    left[0] = '\0';
    left[maxLeftCol] = '\0';

#define	prtlong	(opt->longName != NULL)	/* XXX splint needs a clue */
    if (!(prtshort || prtlong))
	goto out;
    if (prtshort && prtlong) {
	char *dash = F_ISSET(opt, ONEDASH) ? "-" : "--";
	left[0] = '-';
	left[1] = opt->shortName;
	(void) stpcpy(stpcpy(stpcpy(left+2, ", "), dash), opt->longName);
    } else if (prtshort) {
	left[0] = '-';
	left[1] = opt->shortName;
	left[2] = '\0';
    } else if (prtlong) {
	/* XXX --long always padded for alignment with/without "-X, ". */
	char *dash = poptArgType(opt) == POPT_ARG_MAINCALL ? ""
		   : (F_ISSET(opt, ONEDASH) ? "-" : "--");
	const char *longName = opt->longName;
	const char *toggle;
	if (F_ISSET(opt, TOGGLE)) {
	    toggle = "[no]";
	    if (longName[0] == 'n' && longName[1] == 'o') {
		longName += sizeof("no") - 1;
		if (longName[0] == '-')
		    longName++;
	    }
	} else
	    toggle = "";
	(void) stpcpy(stpcpy(stpcpy(stpcpy(left, "    "), dash), toggle), longName);
    }
#undef	prtlong

    if (argDescrip) {
	char * le = left + strlen(left);

	if (F_ISSET(opt, OPTIONAL))
	    *le++ = '[';

	/* Choose type of output */
	if (F_ISSET(opt, SHOW_DEFAULT)) {
	    defs = singleOptionDefaultValue(lineLength, opt, translation_domain);
	    if (defs) {
		char * t = (char*) xmalloc((help ? strlen(help) : 0) +
				strlen(defs) + sizeof(" "));
assert(t);	/* XXX can't happen */
		if (t) {
		    char * te = t;
		    if (help)
			te = stpcpy(te, help);
		    *te++ = ' ';
		    strcpy(te, defs);
		    defs = _free(defs);
		    defs = t;
		}
	    }
	}

	if (opt->argDescrip == NULL) {
	    switch (poptArgType(opt)) {
	    case POPT_ARG_NONE:
		break;
	    case POPT_ARG_VAL:
#ifdef	NOTNOW	/* XXX pug ugly nerdy output */
	    {	long aLong = opt->val;
		int ops = F_ISSET(opt, LOGICALOPS);
		int negate = F_ISSET(opt, NOT);

		/* Don't bother displaying typical values */
		if (!ops && (aLong == 0L || aLong == 1L || aLong == -1L))
		    break;
		*le++ = '[';
		switch (ops) {
		case POPT_ARGFLAG_OR:
		    *le++ = '|';
		    /*@innerbreak@*/ break;
		case POPT_ARGFLAG_AND:
		    *le++ = '&';
		    /*@innerbreak@*/ break;
		case POPT_ARGFLAG_XOR:
		    *le++ = '^';
		    /*@innerbreak@*/ break;
		default:
		    /*@innerbreak@*/ break;
		}
		*le++ = (opt->longName != NULL ? '=' : ' ');
		if (negate) *le++ = '~';
		/*@-formatconst@*/
		le += sprintf(le, (ops ? "0x%lx" : "%ld"), aLong);
		/*@=formatconst@*/
		*le++ = ']';
	    }
#endif
		break;
	    case POPT_ARG_INT:
	    case POPT_ARG_SHORT:
	    case POPT_ARG_LONG:
	    case POPT_ARG_LONGLONG:
	    case POPT_ARG_FLOAT:
	    case POPT_ARG_DOUBLE:
	    case POPT_ARG_STRING:
		*le++ = (opt->longName != NULL ? '=' : ' ');
		le = stpcpy(le, argDescrip);
		break;
	    default:
		break;
	    }
	} else {
	    char *leo;

	    /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
	    if (!strchr(" =(", argDescrip[0]))
		*le++ = ((poptArgType(opt) == POPT_ARG_MAINCALL) ? ' ' :
			 (poptArgType(opt) == POPT_ARG_ARGV) ? ' ' : '=');
	    le = stpcpy(leo = le, argDescrip);

	    /* Adjust for (possible) wide characters. */
	    displaypad = (int)((le - leo) - stringDisplayWidth(argDescrip));
	}
	if (F_ISSET(opt, OPTIONAL))
	    *le++ = ']';
	*le = '\0';
    }

    if (help)
	POPT_fprintf(fp,"  %-*s   ", (int)(maxLeftCol+displaypad), left);
    else {
	POPT_fprintf(fp,"  %s\n", left);
	goto out;
    }

    left = _free(left);
    if (defs)
	help = defs;

    helpLength = strlen(help);
    while (helpLength > lineLength) {
	const char * ch;
	char format[16];

	ch = help + lineLength - 1;
	while (ch > help && !_isspaceptr(ch))
	    ch = POPT_prev_char(ch);
	if (ch == help) break;		/* give up */
	while (ch > (help + 1) && _isspaceptr(ch))
	    ch = POPT_prev_char (ch);
	ch = POPT_next_char(ch);

	/*
	 *  XXX strdup is necessary to add NUL terminator so that an unknown
	 *  no. of (possible) multi-byte characters can be displayed.
	 */
	{   char * fmthelp = xstrdup(help);
	    if (fmthelp) {
		fmthelp[ch - help] = '\0';
		sprintf(format, "%%s\n%%%ds", (int) indentLength);
		/*@-formatconst@*/
		POPT_fprintf(fp, format, fmthelp, " ");
		/*@=formatconst@*/
		free(fmthelp);
	    }
	}

	help = ch;
	while (_isspaceptr(help) && *help)
	    help = POPT_next_char(help);
	helpLength = strlen(help);
    }

    if (helpLength) fprintf(fp, "%s\n", help);
    help = NULL;

out:
    /*@-dependenttrans@*/
    defs = _free(defs);
    /*@=dependenttrans@*/
    left = _free(left);
}
Example #11
0
File: cp.c Project: dennis95/dennix
static void copy(int sourceFd, const char* sourceName, const char* sourcePath,
        int destFd, const char* destName, const char* destPath, bool force,
        bool prompt, bool recursive) {
    struct stat sourceSt, destSt;
    if (fstatat(sourceFd, sourceName, &sourceSt, 0) < 0) {
        warn("stat: '%s'", sourcePath);
        status = 1;
        return;
    }
    bool destExists = true;
    if (fstatat(destFd, destName, &destSt, 0) < 0) {
        if (errno != ENOENT) {
            warn("stat: '%s'", destPath);
            status = 1;
            return;
        }
        destExists = false;
    }
    if (destExists && sourceSt.st_dev == destSt.st_dev &&
            sourceSt.st_ino == destSt.st_ino) {
        warnx("'%s' and '%s' are the same file", sourcePath, destPath);
        status = 1;
        return;
    }
    if (S_ISDIR(sourceSt.st_mode)) {
        if (!recursive) {
            warnx("omitting directory '%s' because -R is not specified",
                    sourcePath);
            status = 1;
            return;
        }
        if (destExists && !S_ISDIR(destSt.st_mode)) {
            warnx("cannot overwrite '%s' with directory '%s'", destPath,
                    sourcePath);
            status = 1;
            return;
        }
        if (!destExists) {
            if (mkdirat(destFd, destName, S_IRWXU) < 0) {
                warn("mkdir: '%s'", destPath);
                status = 1;
                return;
            }
            if (fstatat(destFd, destName, &destSt, 0) < 0) {
                warn("stat: '%s'", destPath);
                status = 1;
                return;
            }
            destExists = true;
        }

        int newSourceFd = openat(sourceFd, sourceName, O_SEARCH | O_DIRECTORY);
        if (newSourceFd < 0) {
            warn("open: '%s'", sourcePath);
            status = 1;
            return;
        }
        DIR* dir = fdopendir(newSourceFd);
        if (!dir) {
            warn("fdopendir: '%s'", sourcePath);
            close(newSourceFd);
            status = 1;
            return;
        }
        int newDestFd = openat(destFd, destName, O_SEARCH | O_DIRECTORY);
        if (newDestFd < 0) {
            warn("open: '%s'", destPath);
            closedir(dir);
            status = 1;
            return;
        }
        struct dirent* dirent = readdir(dir);
        while (dirent) {
            if (strcmp(dirent->d_name, ".") == 0 ||
                    strcmp(dirent->d_name, "..") == 0) {
                dirent = readdir(dir);
                continue;
            }

            char* newSourcePath = malloc(strlen(sourcePath) +
                    strlen(dirent->d_name) + 2);
            if (!newSourcePath) err(1, "malloc");
            stpcpy(stpcpy(stpcpy(newSourcePath, sourcePath), "/"),
                    dirent->d_name);
            char* newDestPath = malloc(strlen(destPath) +
                    strlen(dirent->d_name) + 2);
            if (!newDestPath) err(1, "malloc");
            stpcpy(stpcpy(stpcpy(newDestPath, destPath), "/"), dirent->d_name);

            if (destExists && dirent->d_dev == destSt.st_dev &&
                    dirent->d_ino == destSt.st_ino) {
                warnx("cannot copy directory '%s' into itself '%s'",
                        newSourcePath, destPath);
            } else {
                copy(newSourceFd, dirent->d_name, newSourcePath, newDestFd,
                    dirent->d_name, newDestPath, force, prompt, recursive);
            }

            free(newSourcePath);
            free(newDestPath);

            dirent = readdir(dir);
        }

        closedir(dir);
        close(newDestFd);
    } else if (S_ISREG(sourceSt.st_mode)) {
        int newDestFd;
        if (destExists) {
            if (prompt) {
                fprintf(stderr, "%s: overwrite '%s'? ",
                        program_invocation_short_name, destPath);
                if (!getConfirmation()) return;
            }

            newDestFd = openat(destFd, destName, O_WRONLY | O_TRUNC);
            if (newDestFd < 0) {
                if (force) {
                    if (unlinkat(destFd, destName, 0) < 0) {
                        warn("unlinkat: '%s'", destPath);
                        status = 1;
                        return;
                    }
                } else {
                    warn("open: '%s'", destPath);
                    status = 1;
                    return;
                }
            } else {
                destExists = true;
            }
        }
        if (!destExists) {
            newDestFd = openat(destFd, destName, O_WRONLY | O_CREAT,
                    sourceSt.st_mode & 0777);
            if (newDestFd < 0) {
                warn("open: '%s'", destPath);
                status = 1;
                return;
            }
        }
        int newSourceFd = openat(sourceFd, sourceName, O_RDONLY);
        if (newSourceFd < 0) {
            warn("open: '%s'", sourcePath);
            close(newDestFd);
            status = 1;
            return;
        }

        copyFile(newSourceFd, sourcePath, newDestFd, destPath);
        close(newDestFd);
        close(newSourceFd);
    } else {
        warnx("unsupported file type: '%s'", sourcePath);
        status = 1;
    }
}
Example #12
0
/**
 * Display default value for an option.
 * @param lineLength	display positions remaining
 * @param opt		option(s)
 * @param translation_domain	translation domain
 * @return
 */
static /*@only@*/ /*@null@*/ char *
singleOptionDefaultValue(size_t lineLength,
		const struct poptOption * opt,
		/*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
		/*@null@*/ const char * translation_domain)
		/*@=paramuse@*/
	/*@*/
{
    const char * defstr = D_(translation_domain, "default");
    char * le = (char*) xmalloc(4*lineLength + 1);
    char * l = le;

assert(le);	/* XXX can't happen */
    if (le == NULL) return NULL;
    *le = '\0';
    *le++ = '(';
    le = stpcpy(le, defstr);
    *le++ = ':';
    *le++ = ' ';
  if (opt->arg) {	/* XXX programmer error */
    poptArg arg;
    arg.ptr = opt->arg;
    switch (poptArgType(opt)) {
    case POPT_ARG_VAL:
    case POPT_ARG_INT:
	le += sprintf(le, "%d", arg.intp[0]);
	break;
    case POPT_ARG_SHORT:
	le += sprintf(le, "%hd", arg.shortp[0]);
	break;
    case POPT_ARG_LONG:
	le += sprintf(le, "%ld", arg.longp[0]);
	break;
    case POPT_ARG_LONGLONG:
#if defined(_MSC_VER) || defined(__MINGW32__)
	le += sprintf(le, "%I64d", arg.longlongp[0]);
#else 
        le += sprintf(le, "%lld", arg.longlongp[0]);
#endif
	break;
    case POPT_ARG_FLOAT:
    {	double aDouble = (double) arg.floatp[0];
	le += sprintf(le, "%g", aDouble);
    }	break;
    case POPT_ARG_DOUBLE:
	le += sprintf(le, "%g", arg.doublep[0]);
	break;
    case POPT_ARG_MAINCALL:
	le += sprintf(le, "%p", opt->arg);
	break;
    case POPT_ARG_ARGV:
	le += sprintf(le, "%p", opt->arg);
	break;
    case POPT_ARG_STRING:
    {	const char * s = arg.argv[0];
	if (s == NULL)
	    le = stpcpy(le, "null");
	else {
	    size_t limit = 4*lineLength - (le - l) - sizeof("\"\")");
	    size_t slen;
	    *le++ = '"';
	    strncpy(le, s, limit); le[limit] = '\0'; le += (slen = strlen(le));
	    if (slen == limit && s[limit])
		le[-1] = le[-2] = le[-3] = '.';
	    *le++ = '"';
	}
    }	break;
    case POPT_ARG_NONE:
    default:
	l = _free(l);
	return NULL;
	/*@notreached@*/ break;
    }
  }
    *le++ = ')';
    *le = '\0';

    return l;
}
Example #13
0
static inline void stx_request_process_file(stx_request_t *r,
                                            stx_hashmap_t *open_files)
{
    int fd;
    char filepath[255];
    struct stat sb;
    char *p;
    size_t b_left, min;
    stx_open_file_cache_t *cache;
    
    p = filepath;
    p = stpcpy(p, r->server->webroot);
    
    b_left = p - filepath - 1;
    min = (r->uri_len < b_left) ? r->uri_len : b_left;
    p = stpncpy(p, r->uri_start, min);

    //append default index file when / is requested
    if (*(r->uri_start + r->uri_len - 1) == '/') {
        b_left = p - filepath - 1;
        min = (r->server->index_len < b_left) ? r->server->index_len : b_left;
        p = stpncpy(p, r->server->index, min);
    }
    
    *p = '\0';
    
    if (NULL == (cache = stx_hashmap_cget(open_files, filepath))) { //cache miss
        stx_log(r->server->logger, STX_LOG_INFO, "Open files cache miss: %s", filepath);
        
        if ((fd = open(filepath, O_RDONLY)) == -1) {
            if (ENOENT == errno) {
                r->status = STX_STATUS_NOT_FOUND;
            } else if (EACCES == errno) {
                r->status = STX_STATUS_FORBIDDEN;
            } else {
                r->status = STX_STATUS_ERROR;
                stx_log_syserr(r->server->logger, "open: %s");
            }
            
            return;
        }
        
        if (fstat(fd, &sb) == -1) {
            r->status = STX_STATUS_ERROR;
            stx_log_syserr(r->server->logger, "fstat: %s");
            
            return;
        }
        
        cache = malloc(sizeof(stx_open_file_cache_t));
        if (NULL == cache) {
            r->status = STX_STATUS_ERROR;
            stx_log_syserr(r->server->logger, "malloc: %s");

            return;
        }
        
        cache->fd = fd;
        cache->st_size = sb.st_size;
        if(!stx_hashmap_cput(open_files, filepath, cache)) {
            r->status = STX_STATUS_ERROR;

            return;
        }
    }
    
    cache->count++;
    
    r->status = STX_STATUS_OK;
    r->content_length = cache->st_size;
    r->fd = cache->fd;
}
Example #14
0
static gpgme_error_t
gpgsm_sign(void *engine, gpgme_data_t in, gpgme_data_t out,
           gpgme_sig_mode_t mode, int use_armor, int use_textmode,
           int include_certs, gpgme_ctx_t ctx /* FIXME */)
{
    engine_gpgsm_t gpgsm = engine;
    gpgme_error_t err;
    char *assuan_cmd;
    int i;
    gpgme_key_t key;

    if(!gpgsm)
        return gpg_error(GPG_ERR_INV_VALUE);

    /* FIXME: This does not work as RESET does not reset it so we can't
       revert back to default.  */
    if(include_certs != GPGME_INCLUDE_CERTS_DEFAULT)
    {
        /* FIXME: Make sure that if we run multiple operations, that we
        can reset any previously set value in case the default is
         requested.  */

        if(asprintf(&assuan_cmd, "OPTION include-certs %i", include_certs) < 0)
            return gpg_error_from_errno(errno);
        err = gpgsm_assuan_simple_command(gpgsm->assuan_ctx, assuan_cmd,
                                          NULL, NULL);
        free(assuan_cmd);
        if(err)
            return err;
    }

    for(i = 0; (key = gpgme_signers_enum(ctx, i)); i++)
    {
        const char *s = key->subkeys ? key->subkeys->fpr : NULL;
        if(s && strlen(s) < 80)
        {
            char buf[100];

            strcpy(stpcpy(buf, "SIGNER "), s);
            err = gpgsm_assuan_simple_command(gpgsm->assuan_ctx, buf,
                                              NULL, NULL);
        }
        else
            err = gpg_error(GPG_ERR_INV_VALUE);
        gpgme_key_unref(key);
        if(err)
            return err;
    }

    gpgsm->input_cb.data = in;
    err = gpgsm_set_fd(gpgsm, INPUT_FD, map_input_enc(gpgsm->input_cb.data));
    if(err)
        return err;
    gpgsm->output_cb.data = out;
    err = gpgsm_set_fd(gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0);
    if(err)
        return err;
    gpgsm_clear_fd(gpgsm, MESSAGE_FD);

    err = start(gpgsm, mode == GPGME_SIG_MODE_DETACH
                ? "SIGN --detached" : "SIGN");
    return err;
}
Example #15
0
/* in case it hase been defined as a macro: */
#ifdef bindtextdomain
# undef bindtextdomain
#endif /* bindtextdomain */
char *bindtextdomain(const char *domainname, const char *dirname)
{
#if HAVE_SETENV || HAVE_PUTENV
  char *old_val, *new_val, *cp;
  size_t new_val_len;

  /* This does not make much sense here, but to be compatible, do it: */
  if (domainname == NULL) {
    return NULL;
  }

  /* Compute length of added path element. If we use setenv, then we do NOT
   * need the first bits for NLSPATH=, but why complicate the code for this
   * peanuts.  */
  new_val_len = (sizeof("NLSPATH=") - 1 + strlen(dirname)
                 + sizeof("/%L/LC_MESSAGES/%N.cat"));

  old_val = getenv("NLSPATH");
  if ((old_val == NULL) || (old_val[0] == '\0')) {
      old_val = NULL;
      new_val_len += (1 + sizeof(LOCALEDIR) - 1
                      + sizeof("/%L/LC_MESSAGES/%N.cat"));
  } else {
    new_val_len += strlen(old_val);
  }

  new_val = (char *)malloc(new_val_len);
  if (new_val == NULL) {
    return NULL;
  }

# if HAVE_SETENV
  cp = new_val;
# else
  cp = stpcpy(new_val, "NLSPATH=");
# endif /* HAVE_SETENV */

  cp = stpcpy(cp, dirname);
  cp = stpcpy(cp, "/%L/LC_MESSAGES/%N.cat:");

  if (old_val == NULL) {
# if __STDC__
      stpcpy(cp, LOCALEDIR "/%L/LC_MESSAGES/%N.cat");
# else
      cp = stpcpy(cp, LOCALEDIR);
      stpcpy(cp, "/%L/LC_MESSAGES/%N.cat");
# endif /* __STDC__ */
  } else {
    stpcpy(cp, old_val);
  }

# if HAVE_SETENV
  setenv("NLSPATH", new_val, 1);
  free(new_val);
# else
  putenv(new_val);
  /* Do *not* free the environment entry we just entered. It is used
   * from now on.  */
# endif /* HAVE_SETENV */
#endif /* HAVE_SETENV || HAVE_PUTENV */

  return (char *)domainname;
}
Example #16
0
/*
 * Print reply error info
 */
char *
clnt_sperror (CLIENT * rpch, const char *msg)
{
  char chrbuf[1024];
  struct rpc_err e;
  char *err;
  char *str = _buf ();
  char *strstart = str;
  int len;

  if (str == NULL)
    return NULL;
  CLNT_GETERR (rpch, &e);

  len = sprintf (str, "%s: ", msg);
  str += len;

  str = stpcpy (str, clnt_sperrno (e.re_status));

  switch (e.re_status)
    {
    case RPC_SUCCESS:
    case RPC_CANTENCODEARGS:
    case RPC_CANTDECODERES:
    case RPC_TIMEDOUT:
    case RPC_PROGUNAVAIL:
    case RPC_PROCUNAVAIL:
    case RPC_CANTDECODEARGS:
    case RPC_SYSTEMERROR:
    case RPC_UNKNOWNHOST:
    case RPC_UNKNOWNPROTO:
    case RPC_PMAPFAILURE:
    case RPC_PROGNOTREGISTERED:
    case RPC_FAILED:
      break;

    case RPC_CANTSEND:
    case RPC_CANTRECV:
      len = sprintf (str, "; errno = %s", __strerror_r (e.re_errno,
							chrbuf, sizeof chrbuf));
      str += len;
      break;

    case RPC_VERSMISMATCH:
      len= sprintf (str, _("; low version = %lu, high version = %lu"),
		    e.re_vers.low, e.re_vers.high);
      str += len;
      break;

    case RPC_AUTHERROR:
      err = auth_errmsg (e.re_why);
      str = stpcpy (str, _ ("; why = "));
      if (err != NULL)
	{
	  str = stpcpy (str, err);
	}
      else
	{
	  len = sprintf (str, _("(unknown authentication error - %d)"),
			 (int) e.re_why);
	  str += len;
	}
      break;

    case RPC_PROGVERSMISMATCH:
      len = sprintf (str, _("; low version = %lu, high version = %lu"),
		     e.re_vers.low, e.re_vers.high);
      str += len;
      break;

    default:			/* unknown */
      len = sprintf (str, "; s1 = %lu, s2 = %lu", e.re_lb.s1, e.re_lb.s2);
      str += len;
      break;
    }
  *str = '\n';
  *++str = '\0';
  return (strstart);
}
Example #17
0
PAMH_ARG_DECL(char * create_password_hash,
	const char *password, unsigned int ctrl, int rounds)
{
	const char *algoid;
	char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */
	char *sp;

	if (on(UNIX_MD5_PASS, ctrl)) {
		/* algoid = "$1" */
		return crypt_md5_wrapper(password);
	} else if (on(UNIX_BLOWFISH_PASS, ctrl)) {
		algoid = "$2a$";
	} else if (on(UNIX_SHA256_PASS, ctrl)) {
		algoid = "$5$";
	} else if (on(UNIX_SHA512_PASS, ctrl)) {
		algoid = "$6$";
	} else { /* must be crypt/bigcrypt */
		char tmppass[9];
		char *crypted;

		crypt_make_salt(salt, 2);
		if (off(UNIX_BIGCRYPT, ctrl) && strlen(password) > 8) {
			strncpy(tmppass, password, sizeof(tmppass)-1);
			tmppass[sizeof(tmppass)-1] = '\0';
			password = tmppass;
		}
		crypted = bigcrypt(password, salt);
		memset(tmppass, '\0', sizeof(tmppass));
		password = NULL;
		return crypted;
	}

#ifdef HAVE_CRYPT_GENSALT_R
	if (on(UNIX_BLOWFISH_PASS, ctrl)) {
		char entropy[17];
		crypt_make_salt(entropy, sizeof(entropy) - 1);
		sp = crypt_gensalt_r (algoid, rounds,
				      entropy, sizeof(entropy),
				      salt, sizeof(salt));
	} else {
#endif
		sp = stpcpy(salt, algoid);
		if (on(UNIX_ALGO_ROUNDS, ctrl)) {
			sp += snprintf(sp, sizeof(salt) - 3, "rounds=%u$", rounds);
		}
		crypt_make_salt(sp, 8);
		/* For now be conservative so the resulting hashes
		 * are not too long. 8 bytes of salt prevents dictionary
		 * attacks well enough. */
#ifdef HAVE_CRYPT_GENSALT_R
	}
#endif
	sp = crypt(password, salt);
	if (strncmp(algoid, sp, strlen(algoid)) != 0) {
		/* libxcrypt/libc doesn't know the algorithm, use MD5 */
		pam_syslog(pamh, LOG_ERR,
			   "Algo %s not supported by the crypto backend, "
			   "falling back to MD5\n",
			   on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" :
			   on(UNIX_SHA256_PASS, ctrl) ? "sha256" :
			   on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid);
		memset(sp, '\0', strlen(sp));
		return crypt_md5_wrapper(password);
	}

	return x_strdup(sp);
}
Example #18
0
nis_error
nis_creategroup (const_nis_name group, unsigned int flags)
{
  if (group != NULL && group[0] != '\0')
    {
      size_t grouplen = strlen (group);
      char buf[grouplen + 50];
      char leafbuf[grouplen + 2];
      char domainbuf[grouplen + 2];
      nis_error status;
      nis_result *res;
      char *cp, *cp2;
      nis_object *obj;

      cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1));
      cp = stpcpy (cp, ".groups_dir");
      cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1);
      if (cp2 != NULL && cp2[0] != '\0')
        {
	  *cp++ = '.';
          stpcpy (cp, cp2);
        }
      else
	return NIS_BADNAME;

      obj = calloc (1, sizeof (nis_object));
      if (__builtin_expect (obj == NULL, 0))
	return NIS_NOMEMORY;

      obj->zo_oid.ctime = obj->zo_oid.mtime = time (NULL);
      obj->zo_name = strdup (leafbuf);
      obj->zo_owner = __nis_default_owner (NULL);
      obj->zo_group = __nis_default_group (NULL);
      obj->zo_domain = strdup (domainbuf);
      if (obj->zo_name == NULL || obj->zo_owner == NULL
	  || obj->zo_group == NULL || obj->zo_domain == NULL)
	{
	  free (obj->zo_group);
	  free (obj->zo_owner);
	  free (obj->zo_name);
	  free (obj);
	  return NIS_NOMEMORY;
	}
      obj->zo_access = __nis_default_access (NULL, 0);
      obj->zo_ttl = 60 * 60;
      obj->zo_data.zo_type = NIS_GROUP_OBJ;
      obj->zo_data.objdata_u.gr_data.gr_flags = flags;
      obj->zo_data.objdata_u.gr_data.gr_members.gr_members_len = 0;
      obj->zo_data.objdata_u.gr_data.gr_members.gr_members_val = NULL;

      res = nis_add (buf, obj);
      nis_free_object (obj);
      if (res == NULL)
	return NIS_NOMEMORY;
      status = NIS_RES_STATUS (res);
      nis_freeresult (res);

      return status;
    }
  return NIS_FAIL;
}
Example #19
0
/* line -- min size: MAX_INTERNAL_COMMAND_SIZE + sizeof(errorlevel) * 8
 */
int expandEnvVars(char *ip, char * const line)
{	char *cp, *tp;

	assert(ip);
	assert(line);

/* Return the maximum pointer into parsedline to add 'numbytes' bytes */
#define parsedMax(numbytes)   \
  (line + MAX_INTERNAL_COMMAND_SIZE - 1 - (numbytes))

	cp = line;

	while(*ip) {
	  /* Assume that at least one character is added, place the
		test here to simplify the switch() statement */
	  if(cp >= parsedMax(1))
		return 0;

	  if(*ip == '%') {
		switch(*++ip) {
		  case '\0':
			*cp++ = '%';
			break;

		  case '%':
			*cp++ = *ip++;
			break;

		  case '0':
		  case '1':
		  case '2':
		  case '3':
		  case '4':
		  case '5':
		  case '6':
		  case '7':
		  case '8':
		  case '9':
			if(0 != (tp = find_arg(*ip - '0'))) {
			  if(cp >= parsedMax(strlen(tp)))
				return 0;
			  cp = stpcpy(cp, tp);
			  ip++;
			}
			else
			  *cp++ = '%';
			  /* Let the digit be copied in the cycle */

			break;

#if 0
		  	/* Caused conflicts with some batches,
		  		see %ERRORLEVEL% */
		  case '?':
			/* overflow check: parsedline has that many character
			  "on reserve" */
			cp += sprintf(cp, "%u", errorlevel);
			ip++;
			break;
#endif

		  default:
#if 0
			if(forvar == toupper(*ip)) {    /* FOR hack */
			  *cp++ = '%';			/* let the var be copied in next cycle */
			  break;
			}
#endif
			if((tp = strchr(ip, '%')) != 0) {
				char *evar;
			  *tp = '\0';

			  if((evar = getEnv(ip)) != 0) {
				if(cp >= parsedMax(strlen(evar)))
				  return 0;
				cp = stpcpy(cp, evar);
			  } else if(matchtok(ip, "ERRORLEVEL")) {
				/* overflow check: parsedline has that many character
				  "on reserve" */
				cp += sprintf(cp, "%u", errorlevel);
			  } else if(matchtok(ip, "_CWD") || matchtok(ip, "CD")) {
			  	if(0 == (evar = cwd(0))) {
				    return 0;
			  	} else {
					if(cp >= parsedMax(strlen(evar)))
					  return 0;
					cp = stpcpy(cp, evar);
					free(evar);
			  	}
			  }

			  ip = tp + 1;
			} else
			  *cp++ = '%';
			break;
		}
		continue;
	  }

#if 0
	  if(iscntrl(*ip)) {
		*cp++ = ' ';
		++ip;
	  } else 
#endif
		*cp++ = *ip++;
	}

	assert(cp);
	assert(cp < line + MAX_INTERNAL_COMMAND_SIZE);

	*cp = 0;
	return 1;
}
Example #20
0
static int
decode_poll_exiting(struct tcb *const tcp, const kernel_ulong_t pts)
{
	struct pollfd fds;
	const unsigned int nfds = tcp->u_arg[1];
	const unsigned long size = sizeof(fds) * nfds;
	const kernel_ulong_t start = tcp->u_arg[0];
	const kernel_ulong_t end = start + size;
	kernel_ulong_t cur;
	const unsigned int max_printed =
		abbrev(tcp) ? max_strlen : -1U;
	unsigned int printed;

	static char outstr[1024];
	char *outptr;
#define end_outstr (outstr + sizeof(outstr))

	if (syserror(tcp))
		return 0;
	if (tcp->u_rval == 0) {
		tcp->auxstr = "Timeout";
		return RVAL_STR;
	}

	if (!verbose(tcp) || !start || !nfds ||
	    size / sizeof(fds) != nfds || end < start)
		return 0;

	outptr = outstr;

	for (printed = 0, cur = start; cur < end; cur += sizeof(fds)) {
		if (umove(tcp, cur, &fds) < 0) {
			if (outptr == outstr)
				*outptr++ = '[';
			else
				outptr = stpcpy(outptr, ", ");
			outptr += sprintf(outptr, "%#" PRI_klx, cur);
			break;
		}
		if (!fds.revents)
			continue;
		if (outptr == outstr)
			*outptr++ = '[';
		else
			outptr = stpcpy(outptr, ", ");
		if (printed >= max_printed) {
			outptr = stpcpy(outptr, "...");
			break;
		}

		static const char fmt[] = "{fd=%d, revents=";
		char fdstr[sizeof(fmt) + sizeof(int) * 3];
		sprintf(fdstr, fmt, fds.fd);

		const char *flagstr = sprintflags("", pollflags,
						  (unsigned short) fds.revents);

		if (outptr + strlen(fdstr) + strlen(flagstr) + 1 >=
		    end_outstr - (2 + 2 * sizeof(long) + sizeof(", ], ..."))) {
			outptr = stpcpy(outptr, "...");
			break;
		}
		outptr = stpcpy(outptr, fdstr);
		outptr = stpcpy(outptr, flagstr);
		*outptr++ = '}';
		++printed;
	}

	if (outptr != outstr)
		*outptr++ = ']';

	*outptr = '\0';
	if (pts) {
		const char *str = sprint_timespec(tcp, pts);

		if (outptr + sizeof(", left ") + strlen(str) < end_outstr) {
			outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left ");
			outptr = stpcpy(outptr, str);
		} else {
			outptr = stpcpy(outptr, ", ...");
		}
	}

	if (outptr == outstr)
		return 0;

	tcp->auxstr = outstr;
	return RVAL_STR;
#undef end_outstr
}
int
dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
{
  if (unlikely (cudie == NULL
		|| (INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit
		    && INTUSE(dwarf_tag) (cudie) != DW_TAG_partial_unit)))
    return -1;

  int res = -1;

  struct linelist *linelist = NULL;
  unsigned int nlinelist = 0;

  /* If there are a large number of lines don't blow up the stack.
     Keep track of the last malloced linelist record and free them
     through the next pointer at the end.  */
#define MAX_STACK_ALLOC 4096
  struct linelist *malloc_linelist = NULL;

  /* Get the information if it is not already known.  */
  struct Dwarf_CU *const cu = cudie->cu;
  if (cu->lines == NULL)
    {
      /* Failsafe mode: no data found.  */
      cu->lines = (void *) -1l;
      cu->files = (void *) -1l;

      /* The die must have a statement list associated.  */
      Dwarf_Attribute stmt_list_mem;
      Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list,
						       &stmt_list_mem);

      /* Get the offset into the .debug_line section.  NB: this call
	 also checks whether the previous dwarf_attr call failed.  */
      const unsigned char *lineendp;
      const unsigned char *linep
	= __libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE,
			   (unsigned char **) &lineendp, NULL);
      if (linep == NULL)
	goto out;

      /* Get the compilation directory.  */
      Dwarf_Attribute compdir_attr_mem;
      Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie,
							  DW_AT_comp_dir,
							  &compdir_attr_mem);
      const char *comp_dir = INTUSE(dwarf_formstring) (compdir_attr);

      if (unlikely (linep + 4 > lineendp))
	{
	invalid_data:
	  __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
	  goto out;
	}

      Dwarf *dbg = cu->dbg;
      Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
      unsigned int length = 4;
      if (unlikely (unit_length == DWARF3_LENGTH_64_BIT))
	{
	  if (unlikely (linep + 8 > lineendp))
	    goto invalid_data;
	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
	  length = 8;
	}

      /* Check whether we have enough room in the section.  */
      if (unit_length < 2 + length + 5 * 1
	  || unlikely (linep + unit_length > lineendp))
	goto invalid_data;
      lineendp = linep + unit_length;

      /* The next element of the header is the version identifier.  */
      uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
      if (unlikely (version < 2) || unlikely (version > 4))
	{
	  __libdw_seterrno (DWARF_E_VERSION);
	  goto out;
	}

      /* Next comes the header length.  */
      Dwarf_Word header_length;
      if (length == 4)
	header_length = read_4ubyte_unaligned_inc (dbg, linep);
      else
	header_length = read_8ubyte_unaligned_inc (dbg, linep);
      const unsigned char *header_start = linep;

      /* Next the minimum instruction length.  */
      uint_fast8_t minimum_instr_len = *linep++;

      /* Next the maximum operations per instruction, in version 4 format.  */
      uint_fast8_t max_ops_per_instr = 1;
      if (version >= 4)
	{
	  if (unlikely (lineendp - linep < 5))
	    goto invalid_data;
	  max_ops_per_instr = *linep++;
	  if (unlikely (max_ops_per_instr == 0))
	    goto invalid_data;
	}

      /* Then the flag determining the default value of the is_stmt
	 register.  */
      uint_fast8_t default_is_stmt = *linep++;

      /* Now the line base.  */
      int_fast8_t line_base = (int8_t) *linep++;

      /* And the line range.  */
      uint_fast8_t line_range = *linep++;

      /* The opcode base.  */
      uint_fast8_t opcode_base = *linep++;

      /* Remember array with the standard opcode length (-1 to account for
	 the opcode with value zero not being mentioned).  */
      const uint8_t *standard_opcode_lengths = linep - 1;
      if (unlikely (lineendp - linep < opcode_base - 1))
	goto invalid_data;
      linep += opcode_base - 1;

      /* First comes the list of directories.  Add the compilation
	 directory first since the index zero is used for it.  */
      struct dirlist
      {
	const char *dir;
	size_t len;
	struct dirlist *next;
      } comp_dir_elem =
	{
	  .dir = comp_dir,
	  .len = comp_dir ? strlen (comp_dir) : 0,
	  .next = NULL
	};
      struct dirlist *dirlist = &comp_dir_elem;
      unsigned int ndirlist = 1;

      // XXX Directly construct array to conserve memory?
      while (*linep != 0)
	{
	  struct dirlist *new_dir =
	    (struct dirlist *) alloca (sizeof (*new_dir));

	  new_dir->dir = (char *) linep;
	  uint8_t *endp = memchr (linep, '\0', lineendp - linep);
	  if (endp == NULL)
	    goto invalid_data;
	  new_dir->len = endp - linep;
	  new_dir->next = dirlist;
	  dirlist = new_dir;
	  ++ndirlist;
	  linep = endp + 1;
	}
      /* Skip the final NUL byte.  */
      ++linep;

      /* Rearrange the list in array form.  */
      struct dirlist **dirarray
	= (struct dirlist **) alloca (ndirlist * sizeof (*dirarray));
      for (unsigned int n = ndirlist; n-- > 0; dirlist = dirlist->next)
	dirarray[n] = dirlist;

      /* Now read the files.  */
      struct filelist null_file =
	{
	  .info =
	  {
	    .name = "???",
	    .mtime = 0,
	    .length = 0
	  },
	  .next = NULL
	};
      struct filelist *filelist = &null_file;
      unsigned int nfilelist = 1;

      if (unlikely (linep >= lineendp))
	goto invalid_data;
      while (*linep != 0)
	{
	  struct filelist *new_file =
	    (struct filelist *) alloca (sizeof (*new_file));

	  /* First comes the file name.  */
	  char *fname = (char *) linep;
	  uint8_t *endp = memchr (fname, '\0', lineendp - linep);
	  if (endp == NULL)
	    goto invalid_data;
	  size_t fnamelen = endp - (uint8_t *) fname;
	  linep = endp + 1;

	  /* Then the index.  */
	  Dwarf_Word diridx;
	  get_uleb128 (diridx, linep);
	  if (unlikely (diridx >= ndirlist))
	    {
	      __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
	      goto out;
	    }

	  if (*fname == '/')
	    /* It's an absolute path.  */
	    new_file->info.name = fname;
	  else
	    {
	      new_file->info.name = libdw_alloc (dbg, char, 1,
						 dirarray[diridx]->len + 1
						 + fnamelen + 1);
              char *cp = new_file->info.name;

              if (dirarray[diridx]->dir != NULL)
		{
		  /* This value could be NULL in case the DW_AT_comp_dir
		     was not present.  We cannot do much in this case.
		     The easiest thing is to convert the path in an
                   absolute path.  */
		  cp = stpcpy (cp, dirarray[diridx]->dir);
		}
              *cp++ = '/';
              strcpy (cp, fname);
	      assert (strlen (new_file->info.name)
		      < dirarray[diridx]->len + 1 + fnamelen + 1);
            }

	  /* Next comes the modification time.  */
	  get_uleb128 (new_file->info.mtime, linep);

	  /* Finally the length of the file.  */
	  get_uleb128 (new_file->info.length, linep);

	  new_file->next = filelist;
	  filelist = new_file;
	  ++nfilelist;
	}
      /* Skip the final NUL byte.  */
      ++linep;

      /* Consistency check.  */
      if (unlikely (linep != header_start + header_length))
	{
	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
	  goto out;
	}

        /* We are about to process the statement program.  Initialize the
	   state machine registers (see 6.2.2 in the v2.1 specification).  */
      Dwarf_Word addr = 0;
      unsigned int op_index = 0;
      unsigned int file = 1;
      int line = 1;
      unsigned int column = 0;
      uint_fast8_t is_stmt = default_is_stmt;
      bool basic_block = false;
      bool prologue_end = false;
      bool epilogue_begin = false;
      unsigned int isa = 0;
      unsigned int discriminator = 0;

      /* Apply the "operation advance" from a special opcode
	 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
      inline void advance_pc (unsigned int op_advance)
      {
	addr += minimum_instr_len * ((op_index + op_advance)
				     / max_ops_per_instr);
	op_index = (op_index + op_advance) % max_ops_per_instr;
      }
Example #22
0
char* WEB_getStatus() {
    static char buffer[64];
    char* p = buffer;
    ProgramVector* pv = getProgramVector();
    if(pv == NULL)
        return (char*)"Missing program vector";
    uint8_t err = pv->error;
    switch(err & 0xf0) {
    case NO_ERROR: {
        // p = stpcpy(p, (const char*)"No error");
        p = stpcpy(p, (const char*)"CPU ");
        float percent = (pv->cycles_per_block/pv->audio_blocksize) / (float)3500;
        p = stpcpy(p, itoa(ceilf(percent*100), 10));
        p = stpcpy(p, (const char*)"% Heap ");
        int mem = pv->heap_bytes_used;
        p = stpcpy(p, itoa(mem, 10));
        break;
    }
    case MEM_ERROR:
        p = stpcpy(p, (const char*)"Memory Error 0x");
        p = stpcpy(p, itoa(err, 16));
        break;
    case BUS_ERROR:
        p = stpcpy(p, (const char*)"Bus Error 0x");
        p = stpcpy(p, itoa(err, 16));
        break;
    case USAGE_ERROR:
        p = stpcpy(p, (const char*)"Usage Error 0x");
        p = stpcpy(p, itoa(err, 16));
        break;
    case NMI_ERROR:
        p = stpcpy(p, (const char*)"Non-maskable Interrupt 0x");
        p = stpcpy(p, itoa(err, 16));
        break;
    case HARDFAULT_ERROR:
        p = stpcpy(p, (const char*)"HardFault Error 0x");
        p = stpcpy(p, itoa(err, 16));
        break;
    case PROGRAM_ERROR:
        p = stpcpy(p, (const char*)"Missing or Invalid Program 0x");
        p = stpcpy(p, itoa(err, 16));
        break;
    default:
        p = stpcpy(p, (const char*)"Unknown Error 0x");
        p = stpcpy(p, itoa(err, 16));
        break;
    }
    return buffer;
}
Example #23
0
static void init_history(void)
{
    using_history();
    if (disable_history) return;
    struct stat stat_info;
    if (!stat(".julia_history", &stat_info)) {
        // history file in current dir
        history_file = ".julia_history";
    }
    else {
        char *histenv = getenv("JULIA_HISTORY");
        if (histenv) {
            history_file = histenv;
        }
        else {
#ifndef __WIN32__
            char *home = getenv("HOME");
            if (!home) return;
            asprintf(&history_file, "%s/.julia_history", home);
#else
            char *home = getenv("AppData");
            if (!home) return;
            asprintf(&history_file, "%s/julia/history", home);
#endif
        }
    }
    if (!stat(history_file, &stat_info)) {
        read_history(history_file);
        for (;;) {
            HIST_ENTRY *entry = history_get(history_base);
            if (entry && isspace(entry->line[0]))
                free_history_entry(history_rem(history_base));
            else break;
        }
        int i, j, k;
        for (i=1 ;; i++) {
            HIST_ENTRY *first = history_get(i);
            if (!first) break;
            int length = strlen(first->line)+1;
            for (j = i+1 ;; j++) {
                HIST_ENTRY *child = history_get(j);
                if (!child || !isspace(child->line[0])) break;
                length += strlen(child->line)+1;
            }
            if (j == i+1) continue;
            first->line = (char*)realloc(first->line, length);
            char *p = strchr(first->line, '\0');
            for (k = i+1; k < j; k++) {
                *p = '\n';
                #ifndef __WIN32__
                p = stpcpy(p+1, history_get(i+1)->line);
                #else
                p = strcpy(p+1, history_get(i+1)->line);
                #endif
                free_history_entry(history_rem(i+1));
            }
        }
    }
    else if (errno == ENOENT) {
        write_history(history_file);
    }
    else {
        jl_printf(jl_uv_stderr, "history file error: %s\n", strerror(errno));
        exit(1);
    }
}
Example #24
0
/* Using Unix sockets this way is a security risk.  */
static int
gaih_local(const char *name, const struct gaih_service *service,
		const struct addrinfo *req, struct addrinfo **pai)
{
	struct utsname utsname;
	struct addrinfo *ai = *pai;

	if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST))
		return (GAIH_OKIFUNSPEC | -EAI_NONAME);

	if ((name != NULL) || (req->ai_flags & AI_CANONNAME))
		if (uname(&utsname) < 0)
			return -EAI_SYSTEM;

	if (name != NULL) {
		if (strcmp(name, "localhost") &&
		    strcmp(name, "local") &&
		    strcmp(name, "unix") &&
		    strcmp(name, utsname.nodename))
			return (GAIH_OKIFUNSPEC | -EAI_NONAME);
	}

	if (req->ai_protocol || req->ai_socktype) {
		const struct gaih_typeproto *tp = gaih_inet_typeproto + 1;

		while (tp->name[0]
		    && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0
		       || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
		       || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol))
		) {
			++tp;
		}
		if (! tp->name[0]) {
			if (req->ai_socktype)
				return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
			return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
		}
	}

	*pai = ai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_un)
			+ ((req->ai_flags & AI_CANONNAME)
			? (strlen(utsname.nodename) + 1) : 0));
	if (ai == NULL)
		return -EAI_MEMORY;

	ai->ai_next = NULL;
	ai->ai_flags = req->ai_flags;
	ai->ai_family = AF_LOCAL;
	ai->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM;
	ai->ai_protocol = req->ai_protocol;
	ai->ai_addrlen = sizeof(struct sockaddr_un);
	ai->ai_addr = (void *)ai + sizeof(struct addrinfo);
#if SALEN
	((struct sockaddr_un *)ai->ai_addr)->sun_len = sizeof(struct sockaddr_un);
#endif /* SALEN */

	((struct sockaddr_un *)ai->ai_addr)->sun_family = AF_LOCAL;
	memset(((struct sockaddr_un *)ai->ai_addr)->sun_path, 0, UNIX_PATH_MAX);

	if (service) {
		struct sockaddr_un *sunp = (struct sockaddr_un *)ai->ai_addr;

		if (strchr(service->name, '/') != NULL) {
			if (strlen(service->name) >= sizeof(sunp->sun_path))
				return GAIH_OKIFUNSPEC | -EAI_SERVICE;
			strcpy(sunp->sun_path, service->name);
		} else {
			if (strlen(P_tmpdir "/") + 1 + strlen(service->name) >= sizeof(sunp->sun_path))
				return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
			stpcpy(stpcpy(sunp->sun_path, P_tmpdir "/"), service->name);
		}
	} else {
		/* This is a dangerous use of the interface since there is a time
		   window between the test for the file and the actual creation
		   (done by the caller) in which a file with the same name could
		   be created.  */
		char *buf = ((struct sockaddr_un *)ai->ai_addr)->sun_path;

		if (__path_search(buf, L_tmpnam, NULL, NULL, 0) != 0
		 || __gen_tempname(buf, __GT_NOCREATE, 0) != 0
		) {
			return -EAI_SYSTEM;
		}
	}

	ai->ai_canonname = NULL;
	if (req->ai_flags & AI_CANONNAME)
		ai->ai_canonname = strcpy((char *)(ai + 1) + sizeof(struct sockaddr_un),
				utsname.nodename);
	return 0;
}
Example #25
0
static void update_status(struct svdir *s)
{
	ssize_t sz;
	int fd;
	svstatus_t status;

	/* pid */
	if (pidchanged) {
		fd = open_trunc_or_warn("supervise/pid.new");
		if (fd < 0)
			return;
		if (s->pid) {
			char spid[sizeof(int)*3 + 2];
			int size = sprintf(spid, "%u\n", (unsigned)s->pid);
			write(fd, spid, size);
		}
		close(fd);
		if (rename_or_warn("supervise/pid.new",
				s->islog ? "log/supervise/pid" : "log/supervise/pid"+4))
			return;
		pidchanged = 0;
	}

	/* stat */
	fd = open_trunc_or_warn("supervise/stat.new");
	if (fd < -1)
		return;

	{
		char stat_buf[sizeof("finish, paused, got TERM, want down\n")];
		char *p = stat_buf;
		switch (s->state) {
		case S_DOWN:
			p = stpcpy(p, "down");
			break;
		case S_RUN:
			p = stpcpy(p, "run");
			break;
		case S_FINISH:
			p = stpcpy(p, "finish");
			break;
		}
		if (s->ctrl & C_PAUSE)
			p = stpcpy(p, ", paused");
		if (s->ctrl & C_TERM)
			p = stpcpy(p, ", got TERM");
		if (s->state != S_DOWN)
			switch (s->sd_want) {
			case W_DOWN:
				p = stpcpy(p, ", want down");
				break;
			case W_EXIT:
				p = stpcpy(p, ", want exit");
				break;
			}
		*p++ = '\n';
		write(fd, stat_buf, p - stat_buf);
		close(fd);
	}

	rename_or_warn("supervise/stat.new",
		s->islog ? "log/supervise/stat" : "log/supervise/stat"+4);

	/* supervise compatibility */
	memset(&status, 0, sizeof(status));
	status.time_be64 = SWAP_BE64(s->start.tv_sec + 0x400000000000000aULL);
	status.time_nsec_be32 = SWAP_BE32(s->start.tv_nsec);
	status.pid_le32 = SWAP_LE32(s->pid);
	if (s->ctrl & C_PAUSE)
		status.paused = 1;
	if (s->sd_want == W_UP)
		status.want = 'u';
	else
		status.want = 'd';
	if (s->ctrl & C_TERM)
		status.got_term = 1;
	status.run_or_finish = s->state;
	fd = open_trunc_or_warn("supervise/status.new");
	if (fd < 0)
		return;
	sz = write(fd, &status, sizeof(status));
	close(fd);
	if (sz != sizeof(status)) {
		warn_cannot("write supervise/status.new");
		unlink("supervise/status.new");
		return;
	}
	rename_or_warn("supervise/status.new",
		s->islog ? "log/supervise/status" : "log/supervise/status"+4);
}
Example #26
0
nis_error
nis_addmember (const_nis_name member, const_nis_name group)
{
  if (group != NULL && group[0] != '\0')
    {
      size_t grouplen = strlen (group);
      char buf[grouplen + 14 + NIS_MAXNAMELEN];
      char domainbuf[grouplen + 2];
      nis_result *res, *res2;
      nis_error status;
      char *cp, *cp2;

      cp = rawmemchr (nis_leaf_of_r (group, buf, sizeof (buf) - 1), '\0');
      cp = stpcpy (cp, ".groups_dir");
      cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1);
      if (cp2 != NULL && cp2[0] != '\0')
        {
	  *cp++ = '.';
          stpcpy (cp, cp2);
        }
      res = nis_lookup (buf, FOLLOW_LINKS | EXPAND_NAME);
      if (NIS_RES_STATUS (res) != NIS_SUCCESS)
	{
	  status = NIS_RES_STATUS (res);
	  nis_freeresult (res);
	  return status;
	}
      if (NIS_RES_NUMOBJ (res) != 1
	  || __type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ)
	{
	  nis_freeresult (res);
	  return NIS_INVALIDOBJ;
	}

      u_int gr_members_len
	= NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len;

      nis_name *new_gr_members_val
	= realloc (NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val,
		   (gr_members_len + 1) * sizeof (nis_name));
      if (new_gr_members_val == NULL)
	goto nomem_out;

      NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val
	= new_gr_members_val;

      new_gr_members_val[gr_members_len] = strdup (member);
      if (new_gr_members_val[gr_members_len] == NULL)
	{
	nomem_out:
	  nis_freeresult (res);
	  return NIS_NOMEMORY;
	}
      ++NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len;

      /* Check the buffer bounds are not exceeded.  */
      assert (strlen (NIS_RES_OBJECT(res)->zo_name) + 1 < grouplen + 14);
      cp = stpcpy (buf, NIS_RES_OBJECT(res)->zo_name);
      *cp++ = '.';
      strncpy (cp, NIS_RES_OBJECT (res)->zo_domain, NIS_MAXNAMELEN);
      res2 = nis_modify (buf, NIS_RES_OBJECT (res));
      status = NIS_RES_STATUS (res2);
      nis_freeresult (res);
      nis_freeresult (res2);

      return status;
    }
  else
    return NIS_FAIL;
}
Example #27
0
/* Return the public key for the keygrip GRIP.  The result is stored
   at RESULT.  This function extracts the public key from the private
   key database.  On failure an error code is returned and NULL stored
   at RESULT. */
gpg_error_t
agent_public_key_from_file (ctrl_t ctrl,
                            const unsigned char *grip,
                            gcry_sexp_t *result)
{
  gpg_error_t err;
  int i, idx;
  gcry_sexp_t s_skey;
  char algoname[6];
  char elems[7];
  gcry_sexp_t uri_sexp, comment_sexp;
  const char *uri, *comment;
  size_t uri_length, comment_length;
  char *format, *p;
  void *args[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
                           for comment + end-of-list.  */
  int argidx;
  gcry_sexp_t list, l2;
  const char *s;
  gcry_mpi_t *array;

  (void)ctrl;

  *result = NULL;

  err = read_key_file (grip, &s_skey);
  if (err)
    return err;

  err = key_parms_from_sexp (s_skey, &list,
                            algoname, sizeof algoname,
                            elems, sizeof elems);
  if (err)
    {
      gcry_sexp_release (s_skey);
      return err;
    }

  /* Allocate an array for the parameters and copy them out of the
     secret key.   FIXME: We should have a generic copy function. */
  array = xtrycalloc (strlen(elems) + 1, sizeof *array);
  if (!array)
    {
      err = gpg_error_from_syserror ();
      gcry_sexp_release (list);
      gcry_sexp_release (s_skey);
      return err;
    }

  for (idx=0, s=elems; *s; s++, idx++ )
    {
      l2 = gcry_sexp_find_token (list, s, 1);
      if (!l2)
        {
          /* Required parameter not found.  */
          for (i=0; i<idx; i++)
            gcry_mpi_release (array[i]);
          xfree (array);
          gcry_sexp_release (list);
          gcry_sexp_release (s_skey);
          return gpg_error (GPG_ERR_BAD_SECKEY);
	}
      array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
      gcry_sexp_release (l2);
      if (!array[idx])
        {
          /* Required parameter is invalid. */
          for (i=0; i<idx; i++)
            gcry_mpi_release (array[i]);
          xfree (array);
          gcry_sexp_release (list);
          gcry_sexp_release (s_skey);
          return gpg_error (GPG_ERR_BAD_SECKEY);
	}
    }
  gcry_sexp_release (list);
  list = NULL;

  uri = NULL;
  uri_length = 0;
  uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0);
  if (uri_sexp)
    uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length);

  comment = NULL;
  comment_length = 0;
  comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
  if (comment_sexp)
    comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);

  gcry_sexp_release (s_skey);
  s_skey = NULL;


  /* FIXME: The following thing is pretty ugly code; we should
     investigate how to make it cleaner.  Probably code to handle
     canonical S-expressions in a memory buffer is better suited for
     such a task.  After all that is what we do in protect.c.  Neeed
     to find common patterns and write a straightformward API to use
     them.  */
  assert (sizeof (size_t) <= sizeof (void*));

  format = xtrymalloc (15+7*strlen (elems)+10+15+1+1);
  if (!format)
    {
      err = gpg_error_from_syserror ();
      for (i=0; array[i]; i++)
        gcry_mpi_release (array[i]);
      xfree (array);
      gcry_sexp_release (uri_sexp);
      gcry_sexp_release (comment_sexp);
      return err;
    }

  argidx = 0;
  p = stpcpy (stpcpy (format, "(public-key("), algoname);
  for (idx=0, s=elems; *s; s++, idx++ )
    {
      *p++ = '(';
      *p++ = *s;
      p = stpcpy (p, " %m)");
      assert (argidx < DIM (args));
      args[argidx++] = &array[idx];
    }
  *p++ = ')';
  if (uri)
    {
      p = stpcpy (p, "(uri %b)");
      assert (argidx+1 < DIM (args));
      args[argidx++] = (void *)&uri_length;
      args[argidx++] = (void *)&uri;
    }
  if (comment)
    {
      p = stpcpy (p, "(comment %b)");
      assert (argidx+1 < DIM (args));
      args[argidx++] = (void *)&comment_length;
      args[argidx++] = (void*)&comment;
    }
  *p++ = ')';
  *p = 0;
  assert (argidx < DIM (args));
  args[argidx] = NULL;

  err = gcry_sexp_build_array (&list, NULL, format, args);
  xfree (format);
  for (i=0; array[i]; i++)
    gcry_mpi_release (array[i]);
  xfree (array);
  gcry_sexp_release (uri_sexp);
  gcry_sexp_release (comment_sexp);

  if (!err)
    *result = list;
  return err;
}
Example #28
0
/** \ingroup rpmfi
 * Retrieve file names from header.
 *
 * The representation of file names in package headers changed in rpm-4.0.
 * Originally, file names were stored as an array of absolute paths.
 * In rpm-4.0, file names are stored as separate arrays of dirname's and
 * basename's, * with a dirname index to associate the correct dirname
 * with each basname.
 *
 * This function is used to retrieve file names independent of how the
 * file names are represented in the package header.
 * 
 * @param h		header
 * @param tagN		RPMTAG_BASENAMES | PMTAG_ORIGBASENAMES
 * @param withstate	take file state into account?
 * @retval td		tag data container
 * @return		1 on success
 */
static int fnTag(Header h, rpmTag tagN, int withstate, rpmtd td)
{
    const char **baseNames, **dirNames;
    const char *fileStates = NULL;
    uint32_t *dirIndexes;
    rpm_count_t count, retcount, dncount;
    size_t size = 0;
    rpmTag dirNameTag = RPMTAG_DIRNAMES;
    rpmTag dirIndexesTag = RPMTAG_DIRINDEXES;
    int i, j;
    int rc = 0; /* assume failure */
    struct rpmtd_s bnames, dnames, dixs, fstates;

    if (tagN == RPMTAG_ORIGBASENAMES) {
	dirNameTag = RPMTAG_ORIGDIRNAMES;
	dirIndexesTag = RPMTAG_ORIGDIRINDEXES;
    }

    if (!headerGet(h, tagN, &bnames, HEADERGET_MINMEM)) {
	return 0;		/* no file list */
    }

    (void) headerGet(h, dirNameTag, &dnames, HEADERGET_MINMEM);
    (void) headerGet(h, dirIndexesTag, &dixs, HEADERGET_MINMEM);

    retcount = count = rpmtdCount(&bnames);
    dncount = rpmtdCount(&dnames);

    /* Basic sanity checking for our interrelated tags  */
    if (rpmtdCount(&dixs) != count || dncount < 1 || dncount > count)
	td->flags |= RPMTD_INVALID;

    if (withstate) {
	/* no recorded states means no installed files */
	if (!headerGet(h, RPMTAG_FILESTATES, &fstates, HEADERGET_MINMEM))
	    goto exit;
	if (rpmtdCount(&fstates) != count)
	    td->flags |= RPMTD_INVALID;
	fileStates = fstates.data;
    }

    if (td->flags & RPMTD_INVALID)
	goto exit;

    baseNames = bnames.data;
    dirNames = dnames.data;
    dirIndexes = dixs.data;

    /*
     * fsm, psm and rpmfi assume the data is stored in a single allocation
     * block, until those assumptions are removed we need to jump through
     * a few hoops here and precalculate sizes etc
     */
    for (i = 0; i < count; i++) {
	if (fileStates && !RPMFILE_IS_INSTALLED(fileStates[i])) {
	    retcount--;
	    continue;
	}
	/* Sanity check  directory indexes are within bounds */
	if (dirIndexes[i] >= dncount) {
	    td->flags |= RPMTD_INVALID;
	    break;
	}
	size += strlen(baseNames[i]) + strlen(dirNames[dirIndexes[i]]) + 1;
    }

    if (!(td->flags & RPMTD_INVALID)) {
	char **fileNames = xmalloc(size + (sizeof(*fileNames) * retcount));
	char *t = ((char *) fileNames) + (sizeof(*fileNames) * retcount);
	for (i = 0, j = 0; i < count; i++) {
	    if (fileStates && !RPMFILE_IS_INSTALLED(fileStates[i]))
		continue;
	    fileNames[j++] = t;
	    t = stpcpy( stpcpy(t, dirNames[dirIndexes[i]]), baseNames[i]);
	    *t++ = '\0';
	}

	td->data = fileNames;
	td->count = retcount;
	td->type = RPM_STRING_ARRAY_TYPE;
	td->flags |= RPMTD_ALLOCED;
	rc = 1;
    }

exit:
    rpmtdFreeData(&bnames);
    rpmtdFreeData(&dnames);
    rpmtdFreeData(&dixs);
    /* only safe if the headerGet() on file states was actually called */
    if (fileStates)
	rpmtdFreeData(&fstates);

    return rc;
}
Example #29
0
File: fsm.c Project: nforro/rpm
/**
 * Create (if necessary) directories not explicitly included in package.
 * @param files		file data
 * @param fs		file states
 * @param plugins	rpm plugins handle
 * @return		0 on success
 */
static int fsmMkdirs(rpmfiles files, rpmfs fs, rpmPlugins plugins)
{
    DNLI_t dnli = dnlInitIterator(files, fs, 0);
    struct stat sb;
    const char *dpath;
    int dc = rpmfilesDC(files);
    int rc = 0;
    int i;
    int ldnlen = 0;
    int ldnalloc = 0;
    char * ldn = NULL;
    short * dnlx = NULL; 

    dnlx = (dc ? xcalloc(dc, sizeof(*dnlx)) : NULL);

    if (dnlx != NULL)
    while ((dpath = dnlNextIterator(dnli)) != NULL) {
	size_t dnlen = strlen(dpath);
	char * te, dn[dnlen+1];

	dc = dnli->isave;
	if (dc < 0) continue;
	dnlx[dc] = dnlen;
	if (dnlen <= 1)
	    continue;

	if (dnlen <= ldnlen && rstreq(dpath, ldn))
	    continue;

	/* Copy as we need to modify the string */
	(void) stpcpy(dn, dpath);

	/* Assume '/' directory exists, "mkdir -p" for others if non-existent */
	for (i = 1, te = dn + 1; *te != '\0'; te++, i++) {
	    if (*te != '/')
		continue;

	    *te = '\0';

	    /* Already validated? */
	    if (i < ldnlen &&
		(ldn[i] == '/' || ldn[i] == '\0') && rstreqn(dn, ldn, i))
	    {
		*te = '/';
		/* Move pre-existing path marker forward. */
		dnlx[dc] = (te - dn);
		continue;
	    }

	    /* Validate next component of path. */
	    rc = fsmStat(dn, 1, &sb); /* lstat */
	    *te = '/';

	    /* Directory already exists? */
	    if (rc == 0 && S_ISDIR(sb.st_mode)) {
		/* Move pre-existing path marker forward. */
		dnlx[dc] = (te - dn);
	    } else if (rc == RPMERR_ENOENT) {
		*te = '\0';
		mode_t mode = S_IFDIR | (_dirPerms & 07777);
		rpmFsmOp op = (FA_CREATE|FAF_UNOWNED);

		/* Run fsm file pre hook for all plugins */
		rc = rpmpluginsCallFsmFilePre(plugins, NULL, dn, mode, op);

		if (!rc)
		    rc = fsmMkdir(dn, mode);

		if (!rc) {
		    rc = rpmpluginsCallFsmFilePrepare(plugins, NULL, dn, dn,
						      mode, op);
		}

		/* Run fsm file post hook for all plugins */
		rpmpluginsCallFsmFilePost(plugins, NULL, dn, mode, op, rc);

		if (!rc) {
		    rpmlog(RPMLOG_DEBUG,
			    "%s directory created with perms %04o\n",
			    dn, (unsigned)(mode & 07777));
		}
		*te = '/';
	    }
	    if (rc)
		break;
	}
	if (rc) break;

	/* Save last validated path. */
	if (ldnalloc < (dnlen + 1)) {
	    ldnalloc = dnlen + 100;
	    ldn = xrealloc(ldn, ldnalloc);
	}
	if (ldn != NULL) { /* XXX can't happen */
	    strcpy(ldn, dn);
	    ldnlen = dnlen;
	}
    }
    free(dnlx);
    free(ldn);
    dnlFreeIterator(dnli);

    return rc;
}
Example #30
0
int
copyinout(Ftw_t* ftw)
{
	register File_t*	f = &state.out->file;
	register char*		s;
	register off_t		c;
	register ssize_t	n;
	register int		rfd;
	register int		wfd;

	if (getfile(state.out, f, ftw) && selectfile(state.out, f))
	{
		s = f->name;
		f->name = stash(&state.out->path.copy, NiL, state.pwdlen + f->namesize);
		strcpy(stpcpy(f->name, state.pwd), s + (*s == '/'));
		if ((wfd = openout(state.out, f)) >= 0)
		{
			if ((rfd = openin(state.out, f)) >= 0)
			{
#if defined(SEEK_DATA) && defined(SEEK_HOLE)
				off_t		data;
				off_t		hole;
				int		more;

				data = 0;
				more = 1;
				while (more)
				{
					if ((hole = lseek(rfd, data, SEEK_HOLE)) < data)
					{
						hole = lseek(rfd, 0, SEEK_END);
						more = 0;
					}
					while ((c = hole - data) > 0)
					{
						if (c > state.buffersize)
							c = state.buffersize;
						if (lseek(rfd, data, SEEK_SET) != data || (n = read(rfd, state.tmp.buffer, (size_t)c)) <= 0)
						{
							error(ERROR_SYSTEM|2, "%s: read error", f->name);
							more = 0;
							break;
						}
						if (lseek(wfd, data, SEEK_SET) != data || write(wfd, state.tmp.buffer, n) != n)
						{
							error(ERROR_SYSTEM|2, "%s: write error", f->name);
							more = 0;
							break;
						}
						state.out->io->count += n;
						data += n;
					}
					if (!more)
						break;
					if ((data = lseek(rfd, hole, SEEK_DATA)) < hole)
					{
						if ((data = lseek(rfd, -1, SEEK_END)) < 0 || (data + 1) > hole && (lseek(wfd, data, SEEK_SET) != data || write(wfd, "", 1) != 1))
							error(ERROR_SYSTEM|2, "%s: write error", f->name);
						state.out->io->count += 1;
						break;
					}
				}
#else
				holeinit(wfd);
				for (c = f->st->st_size; c > 0; c -= n)
				{
					if ((n = read(rfd, state.tmp.buffer, (size_t)((c > state.buffersize) ? state.buffersize : c))) <= 0)
					{
						error(ERROR_SYSTEM|2, "%s: read error", f->name);
						break;
					}
					if (holewrite(wfd, state.tmp.buffer, n) != n)
					{
						error(ERROR_SYSTEM|2, "%s: write error", f->name);
						break;
					}
					state.out->io->count += n;
				}
				holedone(wfd);
#endif
				closeout(state.out, f, wfd);
				closein(state.out, f, rfd);
				setfile(state.out, f);
				listentry(f);
			}
			else
				closeout(state.out, f, wfd);
		}
		else if (wfd != -1)
			listentry(f);
	}
	return 0;
}