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

时间:2010-12-25 08:52:01

标签: c++ linux segmentation-fault

我已经测试了程序的加密部分,它适用于单个文件,甚至是“file1,file2,file3”之类的东西,但它不适用于目录。代码对我来说很好,但是在执行它时会给我一个分段错误。

它应该加密目录中的文件,并使用新的扩展名(旧名称+“.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;

    }*/

}

2 个答案:

答案 0 :(得分:2)

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

我认为你的意思是== NULL

答案 1 :(得分:2)

LS功能存在许多问题。首先,您应该直接返回vector<string>而不是使用逗号将数据打包在string中以分隔值。这样可以省去对explode函数的调用,如果目录中包含带逗号的文件名(这是Linux上的有效名称),则不会中断。

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

您至少应该像这样重写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<string>并重写它:

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;
}