Linux 上目录中的文件加密问题

发布于 2024-10-08 19:54:49 字数 3651 浏览 2 评论 0原文

我已经测试了程序的加密部分,它对于单个文件甚至“文件1,文件2,文件3”之类的文件都可以正常工作,但它不适用于目录。该代码对我来说看起来不错,但是在执行时它给了我一个分段错误。

它应该加密目录中的文件,并使用新扩展名(旧名称+“.wbf”)将它们写入同一目录中,并通过相反的扩展名删除进行解密。我只会发布处理文件的代码部分,处理单个文件的 do_crypt 函数工作得很好,我认为这不是我的问题的根源。

    // PHP explode function

    vector<string> explode (string text, char separator)

    {

        vector<string> split;

        int last_trip = 0, pos = 0;

        text += separator;

        for (pos = 0; pos < text.size(); pos++)

        {

            if (text[pos] != separator)

            {

                // continue with iteration

            }

            else

            {

                split.push_back(text.substr(last_trip, pos - last_trip));

                last_trip = pos + 1;

            }

        }

        return split;

    };

    // LINUX -- directory listing function
    string LS (string dir)
    {
        DIR *dp;
        vector<string> files;
        struct dirent *dirp;
        if ((dp = opendir(dir.c_str())) = NULL)
        {
            cout << "Error (" << errno << ") opening " << dir << endl;
            //return errno;
        }
        while ((dirp = readdir(dp)) != NULL)
        {
            files.push_back(string(dirp->d_name));
        }
        closedir(dp);
        string explosive = "";
        for (int i = 0; i < files.size(); i++)
        {
            explosive += files[i];
            if (i != (files.size() - 1)) { explosive += ','; } 
        }
        return 0;
    }

// various functions for encryption

int main (int argc, char* argv[])

{

    cout << "\t! ENCRYPTR -- File encryption utility written by WBlinder, 2010. !" << endl << endl;

    cout << "\t\t\t\tOPTIONS:" << endl;

    cout << "\t\t\t1\tCRYPT A FILE" << endl << "\t\t\t2\tDECRYPT A FILE" << endl << endl;

    cout << "choice > ";

    int opt;

    cin >> opt;

    string sin, sout;

    string dummy; getline(cin, dummy);

    /*cout << "input files > ";

    cout.clear(); cin.clear();

    getline(cin, sin);

    vector<string> fin = explode(sin, ',');

    cout << "output files > ";

    getline(cin, sout);

    vector <string> fout = explode(sout, ',');

    if (sin.size() != sout.size())

    {

        cout << "NO. INPUT FILES UNEQUAL NO. OUTPUT FILES" << endl;

        return 1;

    }*/
    string dir;
    cout << "dir > "; 
    getline (cin, dir);
    vector<string> input = explode(dir, ',');
    vector<string> output = input;
    switch (opt)
    {
        case 1:
            for (int i = 0; i < output.size(); i++)
            {
                output[i] = output[i] + ".wbf";
            }
            break;
        case 2:
            for (int i = 0; i < output.size(); i++)
            {
                output[i] = output[i].substr(0, (output[i].size() - 4));
            }
            break;
    }

    cout << "password > ";

    getline(cin, key);

    cout << "N > ";

    cin >> N;

    cout << "(768 => fairly secure\t3072 => secure)\nextra rounds > ";

    cin >> drop;

    for (int brick = 0; brick < input.size(); brick++)

    {

        do_crypt(opt, dir + input[brick], dir + output[brick]);

    }

    /*string text;

    cout << "text to split: ";

    getline (cin, text);

    vector<string> tnt = explode(text, '.');

    for (int i = 0; i < tnt.size(); i++)

    {

        cout << i << ": " << tnt[i] << endl;

    }*/

}

I have tested the encryption part of the program and it works just fine for individual files, or even things like "file1,file2,file3" but it doesn't work with directories. The code looks fine to me, however when executing it gives me a segmentation fault.

It's supposed to encrypt files in directory and write them in the same directory with a new extension (old name + ".wbf") and decryption with extension removal upon the opposite. I'm only going to post the parts of code that deal with the files, the do_crypt function that works with individual files works just fine, and I think it's not the source of my problems.

    // PHP explode function

    vector<string> explode (string text, char separator)

    {

        vector<string> split;

        int last_trip = 0, pos = 0;

        text += separator;

        for (pos = 0; pos < text.size(); pos++)

        {

            if (text[pos] != separator)

            {

                // continue with iteration

            }

            else

            {

                split.push_back(text.substr(last_trip, pos - last_trip));

                last_trip = pos + 1;

            }

        }

        return split;

    };

    // LINUX -- directory listing function
    string LS (string dir)
    {
        DIR *dp;
        vector<string> files;
        struct dirent *dirp;
        if ((dp = opendir(dir.c_str())) = NULL)
        {
            cout << "Error (" << errno << ") opening " << dir << endl;
            //return errno;
        }
        while ((dirp = readdir(dp)) != NULL)
        {
            files.push_back(string(dirp->d_name));
        }
        closedir(dp);
        string explosive = "";
        for (int i = 0; i < files.size(); i++)
        {
            explosive += files[i];
            if (i != (files.size() - 1)) { explosive += ','; } 
        }
        return 0;
    }

// various functions for encryption

int main (int argc, char* argv[])

{

    cout << "\t! ENCRYPTR -- File encryption utility written by WBlinder, 2010. !" << endl << endl;

    cout << "\t\t\t\tOPTIONS:" << endl;

    cout << "\t\t\t1\tCRYPT A FILE" << endl << "\t\t\t2\tDECRYPT A FILE" << endl << endl;

    cout << "choice > ";

    int opt;

    cin >> opt;

    string sin, sout;

    string dummy; getline(cin, dummy);

    /*cout << "input files > ";

    cout.clear(); cin.clear();

    getline(cin, sin);

    vector<string> fin = explode(sin, ',');

    cout << "output files > ";

    getline(cin, sout);

    vector <string> fout = explode(sout, ',');

    if (sin.size() != sout.size())

    {

        cout << "NO. INPUT FILES UNEQUAL NO. OUTPUT FILES" << endl;

        return 1;

    }*/
    string dir;
    cout << "dir > "; 
    getline (cin, dir);
    vector<string> input = explode(dir, ',');
    vector<string> output = input;
    switch (opt)
    {
        case 1:
            for (int i = 0; i < output.size(); i++)
            {
                output[i] = output[i] + ".wbf";
            }
            break;
        case 2:
            for (int i = 0; i < output.size(); i++)
            {
                output[i] = output[i].substr(0, (output[i].size() - 4));
            }
            break;
    }

    cout << "password > ";

    getline(cin, key);

    cout << "N > ";

    cin >> N;

    cout << "(768 => fairly secure\t3072 => secure)\nextra rounds > ";

    cin >> drop;

    for (int brick = 0; brick < input.size(); brick++)

    {

        do_crypt(opt, dir + input[brick], dir + output[brick]);

    }

    /*string text;

    cout << "text to split: ";

    getline (cin, text);

    vector<string> tnt = explode(text, '.');

    for (int i = 0; i < tnt.size(); i++)

    {

        cout << i << ": " << tnt[i] << endl;

    }*/

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

辞别 2024-10-15 19:54:49

您的 LS 函数存在很多问题。首先,您应该让它直接返回一个 vector,而不是使用逗号分隔值将数据打包在 string 中。这将节省您对 explode 函数的调用,并且如果目录包含带逗号的文件名(这是 Linux 上的有效名称),也不会中断。

但更大的问题(导致)您的段错误是 return 0 行。由于您的函数被声明为返回一个 string 对象,并且由于 string 类具有来自 const char* 的隐式构造函数,因此它由编译器返回字符串(NULL)。当使用 NULL 指针调用时,此构造函数会引发 logic_error 异常。由于您没有捕获异常,C++ 运行时会调用 abort 函数。此函数在设计上会导致段错误,以便停止执行(如果启用,则会生成核心转储以允许事后调试)。

您至少应该像这样重写您的 LS 函数:

string LS (string dir)
{
    DIR *dp;
    vector<string> files;
    struct dirent *dirp;
    if ((dp = opendir(dir.c_str())) == NULL)
    {
        cout << "Error (" << errno << ") opening " << dir << endl;
        return string();
    }
    while ((dirp = readdir(dp)) != NULL)
    {
        files.push_back(string(dirp->d_name));
    }
    closedir(dp);
    string explosive = "";
    for (int i = 0; i < files.size(); i++)
    {
        explosive += files[i];
        if (i != (files.size() - 1)) { explosive += ','; } 
    }
    return explosive;
}

或者更好的是,更改其签名以返回 vector 并像这样重写它:

vector<string> LS (string dir)
{
    DIR *dp;
    vector<string> files;
    struct dirent *dirp;
    if ((dp = opendir(dir.c_str())) != NULL)
    {
        while ((dirp = readdir(dp)) != NULL)
        {
            files.push_back(string(dirp->d_name));
        }
        closedir(dp);
    }
    else
    {
        cout << "Error (" << errno << ") opening " << dir << endl;
    }
    return files;
}

There is many problem in your LS function. First, you should make it directly return a vector<string> instead of packing the data in a string using a comma to separate value. This would save you a call to explode function, and would not break if the directory contains a filename with a comma in it (which is a valid name on Linux).

But the bigger problem (that is causing) your segfault is the return 0 line. Since your function is declared to return a string object, and since string class has an implicit constructor from const char*, this is interpreted by the compiler as return string(NULL). And when called with a NULL pointer this constructor raise a logic_error exception. As you didn't catch the exception, the C++ runtime call the abort function. This function cause a segfault by design in order to stop execution (and if enabled generate a coredump to allow post-morten debugging).

You should at least rewritte your LS function like that:

string LS (string dir)
{
    DIR *dp;
    vector<string> files;
    struct dirent *dirp;
    if ((dp = opendir(dir.c_str())) == NULL)
    {
        cout << "Error (" << errno << ") opening " << dir << endl;
        return string();
    }
    while ((dirp = readdir(dp)) != NULL)
    {
        files.push_back(string(dirp->d_name));
    }
    closedir(dp);
    string explosive = "";
    for (int i = 0; i < files.size(); i++)
    {
        explosive += files[i];
        if (i != (files.size() - 1)) { explosive += ','; } 
    }
    return explosive;
}

Or better, change its signature to return a vector<string> and rewrite it like that:

vector<string> LS (string dir)
{
    DIR *dp;
    vector<string> files;
    struct dirent *dirp;
    if ((dp = opendir(dir.c_str())) != NULL)
    {
        while ((dirp = readdir(dp)) != NULL)
        {
            files.push_back(string(dirp->d_name));
        }
        closedir(dp);
    }
    else
    {
        cout << "Error (" << errno << ") opening " << dir << endl;
    }
    return files;
}
醉殇 2024-10-15 19:54:49

if ((dp = opendir(dir.c_str())) = NULL)

我认为你的意思是 == NULL

if ((dp = opendir(dir.c_str())) = NULL)

I think you mean == NULL

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文