2016-05-26 2 views
1

Я передаю файл из Linux в Windows, используя библиотеку libssh в режиме SFTP, используя C++ в Windows.«Permission denied» при открытии файла для записи второй раз

Я могу создать файл на стороне 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; 
} 

На повторном запуске того же программы, я получаю сообщение об ошибке:

Can't open file for writing: Permission denied

файл создан не имеющий разрешение на переписывание в нем.

Как это исправить?

+0

Во второй раз, когда вы получаете эту ошибку, может быть «файл по-прежнему используется другим процессом». вы должны убедиться, что вы выпускаете файл после выполнения своих операций. –

+0

Вопрос не имеет ничего общего с sftp или libssh, поскольку вы получаете ошибку при работе с локальным файлом. –

ответ

0

В Windows, open() устарел, и вместо этого вы должны использовать _open() или, даже предпочтительнее, _sopen_s().

_open() имеет дополнительный параметр "ИНТ PMODE", который позволяет устанавливать права доступа к файлам:

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> 
+0

Все еще сталкивается с той же проблемой. Когда я открываю этот файл в блокноте и пытаюсь его отредактировать, у меня нет разрешения на это. –

+0

@akshaysoni Я проверил его в своей системе, действительно, open() создает только файл с разрешениями на чтение, который мешает вам писать его снова. используя _sopen_s(), вы можете указать требуемые права доступа к файлам. Я изменил свой ответ соответственно. – alex

+1

Это много исследований, спасибо. –

4

Вы не закрыть дескриптор файла, как только вы закончите писать:

close(fd); 

Если вы не закрывать ручку, файл заперт в процессе, пока процесс не завершит работу и никакой другой процесс может напишите файл тем временем.

+0

все еще сталкивается с той же проблемой. –

+0

Когда я открываю этот файл в блокноте и пытаюсь его отредактировать, у меня нет разрешения на это. –

Смежные вопросы