【发布时间】:2023-03-28 21:16:01
【问题描述】:
我试图使用系统调用将文件从一个目录复制到另一个目录,但我得到一个“违反段核心”,我不知道为什么,第一个参数是原始目录,第二个是命运目录,第三个没有使用,第四个是我开始复制第一个目录的每个文件的字节位置,我的意思是例如如果 Pos = 4 并且文件是 hello 复制的文件内容将为 o 因为我使用 lseek 移动指向位置 4 并从那里开始复制,这是我的代码:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#define BS 512
#define error(a) {perror(a); exit(1);};
int main(int argc, char *argv[]) //argv1 Dir1 argv2 Dir2 argv3 Fich argv4 Pos
{
DIR *dir1;
DIR *dir2;
struct dirent *lectura1;
struct dirent *lectura2;
struct stat st;
int datos1;
int datos2;
int size;
char path[256] = "";
char path2[256] = "";
char temp[256];
char buf[BS];
int j;
int i;
if(argc != 5)
{
error("Numero de argumentos incorrecto");
}
int Pos = atoi(argv[4]);
if(Pos < 0)
{
error("Pos must be 0 or greater")
}
if((dir1 = opendir(argv[1])) == NULL){error("Failed to open origin dir");}
if((dir2 = opendir(argv[2])) == NULL){error("Failed to open destiny dir");}
while((lectura1 = readdir(dir1)) != NULL)
{
sprintf(path, "%s/%s", argv[1], lectura1->d_name);
lectura2 = readdir(dir2);
sprintf(path2, "%s/%s", argv[2], lectura2->d_name);
if (strcmp(lectura1->d_name, "..") != 0 && strcmp(lectura1->d_name, ".") != 0)
{
if (stat(path, &st) == 0)
{
if (S_ISREG(st.st_mode)) //If is a regular file
{
if((datos1 = open(path, O_RDONLY, 00600)) == -1){error("Failed to open file");} //Opens the target file of Dir1 to copy inside Dir2
size = lseek(datos1,0,SEEK_END);
if (size > Pos) //Check if the size of the file is bigger than the position that indicates the point from which to start copying the file
{
lseek(datos1,Pos,SEEK_SET); //Moves the pointer to the start position of the file1
if((datos2 = open(path2, O_CREAT|O_WRONLY, 00200)) == -1){error("Error al abrir archivo copia");}
lseek(datos2,0,SEEK_SET);
j = BS;
i = 0;
int n = 0;
if ((size - i) < BS)
{
j = size - i;
}
while ((n = read(datos1, buf, BS)) > 0)
{
n = write(datos2, buf, j);
i = i + n;
if ((size - i) < BS)
{
j = size - i;
}
}
close(datos1);
close(datos2);
}
}
}
}
}
close(dir1);
close(dir2);
return 0;
}
【问题讨论】:
-
在不知道命令行参数和相应环境(目录和文件)的情况下,很难重现问题。启用编译器警告并修复它们。
argv[4]不是lseek的正确参数。可能你的意思是Pos。您应该准备好处理部分reads 和writes。返回值将告诉您实际读取或写入了多少字节。在调试器中运行你的程序并检查问题发生在哪里。 -
@Bodo 刚刚用 printf 调试过,它没有打印任何我对 c 来说是新的东西所以你认为这可能是因为文件的名称是 util1 并且我使用了一个没有名为 util1 的函数的 main 或这是一个愚蠢的问题?
-
在我的情况下它因为这一行而崩溃:
lectura2 = readdir(dir2);你在lectura2中得到空值,但你没有在下一行检查它。此外,我将lseek行更改为lseek(datos1,atoi(argv[4]),SEEK_SET);,因为传递字符串指针似乎不正确。 -
@GeorgeNechifor 是的,我的错,有一个名为 Pos 的 int 值是 atoi(argv[4]) 我更正了它在 lseek 上调用 pos,但为什么它在 onlectura2 上为空?我的意思是这个参数应该是一个目录
-
谁在上帝的好地球上教你写代码,比如
if((datos1 = open(path, O_RDONLY, 00600)) == -1){error("Failed to open file");}?!?!?将所有这些都塞进一行(加上 cmets !!)会使您的代码几乎不可读,因此极易出错。这也使得在调试器中单步执行实际上是不可能的。
标签: c linux file directory system-calls