打开第二次写入文件时“权限被拒绝”

时间:2016-05-26 09:09:02

标签: c++ permission-denied

我在Windows上使用C ++在SFTP模式下使用库libssh将文件从Linux传输到Windows。

我可以在Windows端创建一个文件,并使用该程序将其写入一次:

int sftp_read_sync(ssh_session session, sftp_session sftp)
{
  int access_type;
  sftp_file file;
  char* buffer[MAX_XFER_BUF_SIZE];
  int nbytes, nwritten, rc;
  int fd;
  access_type = O_RDONLY;
  file = sftp_open(sftp, "/root/bel1.txt",
                   access_type, 0);
  if (file == NULL) {
      fprintf(stderr, "Can't open file for reading: %s\n",
              ssh_get_error(session));
      return SSH_ERROR;
  }
  fd = open("C:\\Users\\Wipro\\Desktop\\bel6.txt", O_WRONLY | O_CREAT  | O_TRUNC);
  if (fd < 0) {
      fprintf(stderr, "Can't open file for writing: %s\n",
              strerror(errno));
      return SSH_ERROR;
  }
  for (;;) {
      nbytes = sftp_read(file, buffer, sizeof(buffer));
      if (nbytes == 0) {
          break; // EOF
      } else if (nbytes < 0) {
          fprintf(stderr, "Error while reading file: %s\n",
                  ssh_get_error(session));
          sftp_close(file);
          return SSH_ERROR;
      }
      nwritten = write(fd, buffer, nbytes);
      if (nwritten != nbytes) {
          fprintf(stderr, "Error writing: %s\n",
                  strerror(errno));
          sftp_close(file);
          return SSH_ERROR;
      }
  }
  rc = sftp_close(file);
  if (rc != SSH_OK) {
      fprintf(stderr, "Can't close the read file: %s\n",
              ssh_get_error(session));
      return rc;
  }
  return SSH_OK;
}

再次运行同一个程序时,我收到一个错误:

  

无法打开文件进行写入:权限被拒绝

创建的文件没有重写权限。

我该如何纠正?

2 个答案:

答案 0 :(得分:4)

完成写作后,您必须关闭文件句柄:

close(fd);

当您不关闭句柄时,文件将被进程保持锁定状态,直到进程退出,其他进程无法同时写入文件。

答案 1 :(得分:0)

在Windows上,不推荐使用open(),你应该使用_open()或者甚至是首选的_sopen_s()。

_open()有一个可选参数&#34; int pmode&#34;它允许您设置文件权限:

int _open(
   const char *filename,
   int oflag [,
   int pmode] 
);

对于pmode,您可以指定

_S_IREAD
  Only reading permitted.
_S_IWRITE
  Writing permitted. (In effect, permits reading and writing.)
_S_IREAD | _S_IWRITE
  Reading and writing permitted.

所以只需替换您的陈述

fd = open("C:\\Users\\Wipro\\Desktop\\bel6.txt", O_WRONLY | O_CREAT  | O_TRUNC);

fd = _open("C:\\Users\\Wipro\\Desktop\\bel6.txt", O_WRONLY | O_CREAT  | O_TRUNC, _S_IREAD | _S_IWRITE);

你应该没事。有关详细信息,请参阅https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx

由于您使用的是Windows,因此您也可以使用_sopen_s()而不是open()。 _sopen_s()还允许指定文件权限。它的API不同,看起来像

errno_t _sopen_s(
   int* pfh,
   const char *filename,
   int oflag,
   int shflag,
   int pmode
);

根据https://msdn.microsoft.com/en-us/library/w64k0ytk.aspx,参数是

[out] pfh
  The file handle, or -1 in the case of an error.
[in] filename
  File name.
[in] oflag
  The kind of operations allowed.
[in] shflag
  The kind of sharing allowed.
[in] pmode
  Permission setting.

因此,您可以替换您的陈述

fd = open("C:\\Users\\Wipro\\Desktop\\bel6.txt", O_WRONLY | O_CREAT  | O_TRUNC);

int fd;
int err = _sopen_s( &fd, "C:\\Users\\Wipro\\Desktop\\bel6.txt", O_WRONLY | O_CREAT | O_TRUNC, _SH_DENYNO, _S_IREAD | _S_IWRITE );
if (err) {
    fprintf( stderr, "Can't open file for writing: %s\n",
      strerror( errno ) );
    return errno;
  }

https://msdn.microsoft.com/en-us/library/w64k0ytk.aspx精心记录了参数的其他可能值。

最后,无论您使用_open()还是_sopen_s(),您仍应关闭文件(当设置文件权限时):

_close( fh );

最后,您需要以下标题:

#include <io.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <iostream>
#include <sys/stat.h>
#include <errno.h>