Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中的Chmod分配了错误的权限_C_Linux_File_File Permissions_Chmod - Fatal编程技术网

C中的Chmod分配了错误的权限

C中的Chmod分配了错误的权限,c,linux,file,file-permissions,chmod,C,Linux,File,File Permissions,Chmod,下面是我的代码,用于将文件从路径复制到作为目标提供的目录的方法。复制工作正常,但是我的chmod调用为目标中复制的文件分配了错误的权限。如果源中的权限为644,则复制的文件的权限为170或120 我已经试着调试了几个小时,这让我有点疯狂,所以非常感谢任何帮助 void copy_file(char* src, char* dest) { char a; //extract file name through a duplicate ptr char* fname = s

下面是我的代码,用于将文件从路径复制到作为目标提供的目录的方法。复制工作正常,但是我的chmod调用为目标中复制的文件分配了错误的权限。如果源中的权限为644,则复制的文件的权限为170或120

我已经试着调试了几个小时,这让我有点疯狂,所以非常感谢任何帮助

void copy_file(char* src, char* dest) {

    char a;
    //extract file name through a duplicate ptr
    char* fname = strdup(src);
    char* dname = basename(fname);
    //open read and write streams
    FILE* read;
    FILE* write;

    read = fopen(src, "r");
    chdir(dest);
    write = fopen(dname, "w");

    //error checking
    if (read == NULL) //|| (write == NULL))
    {   
        perror("Read Error: ");
        exit(0);
    }

    else if (write == NULL)
    {
        perror("Write Error: ");
        exit(0);
    }

    //write from src to dest char by char
    while (1){
        a = fgetc(read);
        if (a == EOF) 
        {
            break;
        }
        fputc(a, write);
    }

    //close files
    fclose(read);
    fclose(write);

    // this is where I attempt to assign source file permissions
    //and it goes horribly wrong    
    struct stat src_st;
    if(stat(src, &src_st)){
        perror("stat: ");
    }

    chmod(dname, src_st.st_mode);
    printf("%o\n", src_st.st_mode & 0777);
}
你先打电话,然后再打电话。这意味着,当您稍后调用statsrc,&src_st时,没有理由认为stat将访问与fopen相同的文件,或者实际上stat将访问任何文件

如果stat失败,您仍然可以继续调用chmod,这样您就可以将src_st.st_模式中的任何随机垃圾传递给chmod


在调用fclosesrc之前,您应该使用fstatfilenoread和&src_st,而不是调用statsrc和&src_st。

基本问题是您必须立即检查系统调用,如fopen、chdir和stat

例如,我尝试的第一件事是复制文件test.data,test2.data,但没有意识到它需要一个目标目录

dname现在是test.data,与源代码相同

read = fopen(src, "r");     // succeeds
chdir(dest);                // fails
write = fopen(dname, "w");  // blows away test.data, the source
您最终会检查读写,但在损坏完成之后

清除源文件真的很糟糕。代码处理失败的系统调用非常重要。如果你不这样做,它将继续航行,造成混乱和破坏

C中的大多数系统调用返回0表示成功。这是一个反模式,其中返回值是一个错误标志,因此false表示失败,其他任何东西都指示什么类型的错误,尽管stat不使用它,但它使用errno

当它失败时,stat返回-1,这是真的。所以这是错误的方法

struct stat src_st;
if(stat(src, &src_st)){
    perror("stat: ");
}
相反,您必须检查是否为非零

    struct stat src_st;
    if(stat(src, &src_st) != 0 ){
        // Note that I don't use perror, it doesn't provide enough information.
        fprintf(stderr, "Could not stat %s: %s\n", src, strerror(errno));
        exit(1);
    }
你可以猜到这会变得非常乏味,你会忘记,或者每次做的都会略有不同。您需要围绕这些函数编写包装器,以便为您进行错误处理

FILE *fopen_checked( const char *file, const char *mode ) {
    FILE *fp = fopen(file, mode);
    if( file == NULL ) {
        fprintf(stderr, "Could not open '%s' for '%s': %s", file, mode, strerror(errno));
        exit(1);
    }

    return fp;
}
这不是最好的错误处理方法,但至少可以确保代码正确停止并着火

关于chdir的注意事项:如果可以避免,就不要使用它。chdir会影响程序的全局状态、当前工作目录,而全局会增加一切的复杂性。对于一个函数来说,改变目录是非常非常容易的,而不是像你的那样改变回去。现在,您的流程处于一种奇怪的状态

例如,如果复制了某个文件somefile,foo这会将程序保留在foo/中。如果他们真的将_文件复制到了其他文件中,那么foo他们就会试图将foo/otherfile复制到foo/foo/otherfile

并且,由于进程现在位于不同的目录中,因此stat失败。因此,即使是执行chdir的函数也被它弄糊涂了

确保您的函数总是以C语言返回原始目录是非常困难的,并且会使错误处理变得非常复杂。相反,请留在原始目录中,并使用basename等函数将路径连接在一起

最后,避免混合文件操作。使用文件名或文件描述符,但不要同时使用两者。这意味着如果您使用的是fopen,请使用fstat和fchmod。您可能必须使用fileno从文件指针中获取文件描述符


这避免了必须携带并保持同步两段数据,即文件描述符和文件名。它还避免了chdir或重命名甚至删除文件的问题,只要文件描述符保持打开状态,它就会继续工作。

这也是一个问题:

char a;

...

while (1){
    a = fgetc(read);
    if (a == EOF) 
    {
        break;
    }
    fputc(a, write);
}
fgetc返回int,而不是char。Per,:

7.21.7.1 fgetc功能

概要


假设sizeof int>sizeof char,char值是有符号的,2个补码整数,而EOF是一个定义为-1的int,所有非常常见的值,读取char a=fgetc流的文件;读取有效的0xFF字符值时将失败。如果实现的默认char值是unsigned char,char a=fgetc stream;将永远不会生成与EOF匹配的值。

请阅读.char a。。。a=fgetcread;这是错误的。fgetc返回int的原因。fname=strduprc;是内存泄漏。您从未释放fname。如果fopensrc,r和fopendname,w都失败,您的代码将显示来自dname的错误,但声明它来自读取src.exit0,表示成功终止。使用exitEXIT_FAILURE处理错误。这很有效,非常感谢仍在使用C的人!!
char a;

...

while (1){
    a = fgetc(read);
    if (a == EOF) 
    {
        break;
    }
    fputc(a, write);
}
#include <stdio.h>
int fgetc(FILE *stream);