C中的Chmod分配了错误的权限
下面是我的代码,用于将文件从路径复制到作为目标提供的目录的方法。复制工作正常,但是我的chmod调用为目标中复制的文件分配了错误的权限。如果源中的权限为644,则复制的文件的权限为170或120 我已经试着调试了几个小时,这让我有点疯狂,所以非常感谢任何帮助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
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);