示例#1
0
文件: v4.c 项目: ewxrjk/sftpserver
void sftp_v456_sendattrs(struct sftpjob *job, const struct sftpattr *attrs) {
  const uint32_t valid = attrs->valid & protocol->attrmask;

  sftp_send_uint32(job->worker, valid);
  sftp_send_uint8(job->worker, attrs->type);
  if(valid & SSH_FILEXFER_ATTR_SIZE)
    sftp_send_uint64(job->worker, attrs->size);
  if(valid & SSH_FILEXFER_ATTR_OWNERGROUP) {
    sftp_send_path(job, job->worker, attrs->owner);
    sftp_send_path(job, job->worker, attrs->group);
  }
  if(valid & SSH_FILEXFER_ATTR_PERMISSIONS)
    sftp_send_uint32(job->worker, attrs->permissions);
  /* lftp 3.1.3 expects subsecond time fields even if the corresonding time is
   * absent.  It sends no identifying information so we cannot enable a
   * workaround for this bizarre bug.  lftp 3.5.9 gets this right as does
   * WinSCP. */
  if(valid & SSH_FILEXFER_ATTR_ACCESSTIME) {
    sftp_send_uint64(job->worker, attrs->atime.seconds);
    if(valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES)
      sftp_send_uint32(job->worker, attrs->atime.nanoseconds);
  }
  if(valid & SSH_FILEXFER_ATTR_CREATETIME) {
    sftp_send_uint64(job->worker, attrs->createtime.seconds);
    if(valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES)
      sftp_send_uint32(job->worker, attrs->createtime.nanoseconds);
  }
  if(valid & SSH_FILEXFER_ATTR_MODIFYTIME) {
    sftp_send_uint64(job->worker, attrs->mtime.seconds);
    if(valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES)
      sftp_send_uint32(job->worker, attrs->mtime.nanoseconds);
  }
  if(valid & SSH_FILEXFER_ATTR_CTIME) {
    sftp_send_uint64(job->worker, attrs->ctime.seconds);
    if(valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES)
      sftp_send_uint32(job->worker, attrs->ctime.nanoseconds);
  }
  if(valid & SSH_FILEXFER_ATTR_ACL) {
    sftp_send_string(job->worker, attrs->acl);
  }
  if(valid & SSH_FILEXFER_ATTR_BITS) {
    sftp_send_uint32(job->worker, attrs->attrib_bits);
    if(protocol->version >= 6)
      sftp_send_uint32(job->worker, attrs->attrib_bits_valid);
  }
  if(valid & SSH_FILEXFER_ATTR_TEXT_HINT) {
    sftp_send_uint8(job->worker, attrs->text_hint);
  }
  if(valid & SSH_FILEXFER_ATTR_MIME_TYPE) {
    sftp_send_string(job->worker, attrs->mime_type);
  }
  if(valid & SSH_FILEXFER_ATTR_LINK_COUNT) {
    sftp_send_uint32(job->worker, attrs->link_count);
  }
  /* We don't implement untranslated-name yet */
}
示例#2
0
文件: v4.c 项目: ewxrjk/sftpserver
/* Send a filename list as found in an SSH_FXP_NAME response.  The response
 * header and so on must be generated by the caller. */
void sftp_v456_sendnames(struct sftpjob *job, int nnames,
                         const struct sftpattr *names) {
  /* We'd like to know what year we're in for dates in longname */
  sftp_send_uint32(job->worker, nnames);
  while(nnames > 0) {
    sftp_send_path(job, job->worker, names->name);
    protocol->sendattrs(job, names);
    ++names;
    --nnames;
  }
}
示例#3
0
文件: v4.c 项目: ewxrjk/sftpserver
/* Command code for the various _*STAT calls.  rc is the return value
 * from *stat() and SB is the buffer. */
static uint32_t sftp_v456_stat_core(struct sftpjob *job, int rc,
                                    const struct stat *sb, const char *path) {
  struct sftpattr attrs;
  uint32_t flags;

  if(!rc) {
    pcheck(sftp_parse_uint32(job, &flags));
    sftp_stat_to_attrs(job->a, sb, &attrs, flags, path);
    sftp_send_begin(job->worker);
    sftp_send_uint8(job->worker, SSH_FXP_ATTRS);
    sftp_send_uint32(job->worker, job->id);
    protocol->sendattrs(job, &attrs);
    sftp_send_end(job->worker);
    return HANDLER_RESPONDED;
  } else
    return HANDLER_ERRNO;
}
示例#4
0
void sftp_send_begin(struct worker *w) {
  w->bufused = 0;
  sftp_send_uint32(w, 0);                    /* placeholder for length */
}
示例#5
0
文件: v6.c 项目: pyokagan/sftpserver
uint32_t sftp_v6_realpath(struct sftpjob *job) {
  char *path, *compose, *resolvedpath;
  uint8_t control_byte = SSH_FXP_REALPATH_NO_CHECK;
  unsigned rpflags = 0;
  struct stat sb;
  struct sftpattr attrs;

  pcheck(sftp_parse_path(job, &path));
  if(job->left) {
    pcheck(sftp_parse_uint8(job, &control_byte));
    while(job->left) {
      pcheck(sftp_parse_path(job, &compose));
      if(compose[0] == '/')
        path = compose;
      else {
        char *newpath = sftp_alloc(job->a, strlen(path) + strlen(compose) + 2);

        strcpy(newpath, path);
        strcat(newpath, "/");
        strcat(newpath, compose);
        path = newpath;
      }
    }
  }
  D(("sftp_v6_realpath %s %#x", path, control_byte));
  switch(control_byte) {
  case SSH_FXP_REALPATH_NO_CHECK:
    /* Don't follow links and don't fail if the path doesn't exist */
    rpflags = 0;
    break;
  case SSH_FXP_REALPATH_STAT_IF:
    /* Follow links but don't fail if the path doesn't exist */
    rpflags = RP_READLINK;
    break;
  case SSH_FXP_REALPATH_STAT_ALWAYS:
    /* Follow links and fail if the path doesn't exist */
    rpflags = RP_READLINK|RP_MUST_EXIST;
    break;
  default:
    return SSH_FX_BAD_MESSAGE;
  }
  if(!(resolvedpath = sftp_find_realpath(job->a, path, rpflags)))
    return HANDLER_ERRNO;
  D(("...real path is %s", resolvedpath));
  switch(control_byte) {
  case SSH_FXP_REALPATH_NO_CHECK:
    /* Don't stat, send dummy attributes */
    memset(&attrs, 0, sizeof attrs);
    attrs.name = resolvedpath;
    break;
  case SSH_FXP_REALPATH_STAT_IF:
    /* stat as hard as we can but accept failure if it's just not there */
    if(stat(resolvedpath, &sb) >= 0 || lstat(resolvedpath, &sb) >= 0)
      sftp_stat_to_attrs(job->a, &sb, &attrs, 0xFFFFFFFF, resolvedpath);
    else {
      memset(&attrs, 0, sizeof attrs);
      attrs.name = resolvedpath;
    }
    break;
  case SSH_FXP_REALPATH_STAT_ALWAYS:
    /* stat and error on failure */
    if(stat(resolvedpath, &sb) >= 0 || lstat(resolvedpath, &sb) >= 0)
      sftp_stat_to_attrs(job->a, &sb, &attrs, 0xFFFFFFFF, resolvedpath);
    else
      /* Can only happen if path is deleted between realpath call and stat */
      return HANDLER_ERRNO;
    break;
  }
  sftp_send_begin(job->worker);
  sftp_send_uint8(job->worker, SSH_FXP_NAME);
  sftp_send_uint32(job->worker, job->id);
  protocol->sendnames(job, 1, &attrs);
  sftp_send_end(job->worker);
  return HANDLER_RESPONDED;
}