예제 #1
0
static int
ftpdir (char *dir, struct ftpdir_host *host)
{
  int data;
  int rd;
  error_t err;
  static void *copy_buf = 0;
  struct ftp_conn *conn = host->conn;
  char *host_name = host->name;

  err = ftp_conn_start_dir (conn, dir, &data);
  if (err)
    {
      error (0, err, "%s:%s", host_name, dir);
      return err;
    }

  if (! copy_buf)
    {
      copy_buf = valloc (COPY_SZ);
      if (! copy_buf)
	error (12, ENOMEM, "Cannot allocate copy buffer");
    }

  while ((rd = read (data, copy_buf, COPY_SZ)) > 0)
    do
      {
	int wr = write (1, copy_buf, rd);
	if (wr < 0)
	  error (13, errno, "stdout");
	rd -= wr;
      }
    while (rd > 0);
  if (rd != 0)
    {
      error (0, errno, "%s:%s", host_name, dir);
      return errno;
    }

  close (data);

  err = ftp_conn_finish_transfer (conn);
  if (err)
    {
      error (0, err, "%s:%s", host_name, dir);
      return err;
    }

  return 0;
}
예제 #2
0
파일: names.c 프로젝트: GNUHurdTR/hurd
/* Read filenames from FD, calling ADD_NAME for each new NAME (HOOK is passed
   to ADD_NAME).  FD and STATE should be returned from start_get_names.  If
   this function returns EAGAIN, then it should be called again to finish the
   job (possibly after calling select on FD); if it returns 0, then it is
   finishe,d and FD and STATE are deallocated.  */
error_t
ftp_conn_cont_get_names (struct ftp_conn *conn, int fd, void *state,
			 ftp_conn_add_name_fun_t add_name, void *hook)
{
  char *p, *nl;
  ssize_t rd;
  size_t name_len;
  error_t err = 0;
  struct get_names_state *s = state;
  int (*icheck) (struct ftp_conn *conn) = conn->hooks->interrupt_check;

  /* We always consume full lines, so we know that we have to read more when
     we first get called.  */
  rd = read (fd, s->buf + s->buf_len, sizeof (s->buf) - s->buf_len);
  if (rd < 0)
    {
      err = errno;
      goto finished;
    }

  if (icheck && (*icheck) (conn))
    {
      err = EINTR;
      goto finished;
    }

  if (rd == 0)
    /* EOF */
    if (s->buf_len == 0)
      /* We're done!  Clean up and return the result in NAMES.  */
      goto finished;
    else
      /* Partial line at end of file?  */
      nl = s->buf + s->buf_len;
  else
    /* Look for a new line in what we read (we know that there weren't any in
       the buffer before that).  */
    {
      nl = memchr (s->buf + s->buf_len, '\n', rd);
      s->buf_len += rd;
    }

  if (!nl && s->buf_len < sizeof (s->buf))
    /* We didn't find any newlines (which implies we didn't hit EOF), and we
       still have room to grow the buffer, so just wait until next time to do
       anything.  */
    return EAGAIN;

  /* Where we start parsing.  */
  p = s->buf;

  do
    {
      /* Fill in S->name, possibly extending it from a previous buffer.  */
      name_len = (nl ? nl - p : s->buf + s->buf_len - p);
      if (name_len > 0 && p[name_len - 1] == '\r')
	name_len--;
      if (name_len > 0)
	/* Extending s->name.  */
	{
	  size_t old_len = s->name_len;
	  size_t total_len = old_len + name_len + 1;

	  if (total_len > s->name_alloced)
	    {
	      char *new_name = realloc (s->name, total_len);
	      if (! new_name)
		goto enomem;
	      s->name = new_name;
	      s->name_alloced = total_len;
	    }

	  strncpy (s->name + old_len, p, name_len);
	  s->name[old_len + name_len] = '\0';
	  s->name_len = total_len - 1;
	}

      if (nl)
	{
	  char *name = s->name;

	  if (conn->syshooks.basename)
	    /* Fixup any screwy names returned by the server.  */
	    {
	      err = (*conn->syshooks.basename) (conn, &name);
	      if (err)
		goto finished;
	    }

	  /* Call the callback function to process the current entry.  */
	  err = (*add_name) (name, hook);

	  if (name < s->name || name > s->name + s->name_len)
	    /* User-allocated NAME from the fix_nlist_name hook.  */
	    free (name);

	  if (err)
	    goto finished;

	  s->name_len = 0;
	  s->name_partial = 0;

	  p = nl + 1;
	  nl = memchr (p, '\n', s->buf + s->buf_len - p);
	}
      else
	/* We found no newline, so the name extends past what we read; we'll
	   try to read more next time.  */
	{
	  s->name_partial = 1;
	  /* Skip over the partial name for the next iteration.  */
	  p += name_len;
	}
    }
  while (nl);

  /* Move any remaining characters in the buffer to the beginning for the
     next call.  */
  s->buf_len -= (p - s->buf);
  if (s->buf_len > 0)
    memmove (s->buf, p, s->buf_len);

  /* Try again later.  */
  return EAGAIN;

enomem:
  /* Some memory allocation failed.  */
  err = ENOMEM;

finished:
  /* We're finished (with an error if ERR != 0), deallocate everything &
     return.  */
  if (s->name)
    free (s->name);
  free (s);
  close (fd);

  if (err && rd > 0)
    ftp_conn_abort (conn);
  else if (err)
    ftp_conn_finish_transfer (conn);
  else
    err = ftp_conn_finish_transfer (conn);

  return err;
}