【问题标题】:Copy files of directory into another using system calls on linux在linux上使用系统调用将目录文件复制到另一个目录
【发布时间】: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


【解决方案1】:

是的,它似乎是这样工作的:

#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);
        sprintf(path2, "%s/%s", argv[2], lectura1->d_name); //<-- changed param

        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);
                    }
                }
            }
        }
    }
    closedir(dir1);
    closedir(dir2); // <-- changed call
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-18
    • 2012-02-15
    • 1970-01-01
    • 2013-09-28
    • 1970-01-01
    相关资源
    最近更新 更多