1
int ScanDirectories(const char *dirname, struct images *imagesHeadPtr, struct filesToParse *filesHeadPtr)
{
    // scan the directory and store the entries in a buffer 


DIR *dir;
struct dirent *ent;
int jpgs = 0, pngs = 0;
int totalFiles = 0;
int filesToScan = 0;
char name[256];
char *tmp = malloc(sizeof(char));

if((dir = opendir(dirname)) == NULL)
{
    perror("Unable to open directory");
    DisplayFolderNotFound();
    return(0);
}

while((ent = readdir(dir)) != NULL)
{
    strcpy(name, ent->d_name);
    strncpy(tmp, name, 1);
    if(strcmp(tmp, ".") == 0)   //Not valid directories. These are dir's created by system and are hidden.
    continue;

    char dirCopy[strlen(dirname)+ strlen(name) + 1 /* for slash */  + 1 /*for null character*/];

    strcpy(dirCopy, dirname);        
    strcat(dirCopy, "/");
    strcat(dirCopy, name);

    struct stat s;

    if( stat(dirCopy, &s) == 0 )
    {
        if( s.st_mode & S_IFDIR )
        {
            //              it's a directory
            //              printf("Directory [%s]\n", dirCopy);
            ScanDirectories(dirCopy, imagesHeadPtr, filesHeadPtr); //Already inside a dir, recursively traverse it.
        }
        else if( s.st_mode & S_IFREG )
        {
            //it's a file
            //printf("File [%s]\n", name);

            ++totalFiles;
        }
        else
        {
            //something else
        }
    }
    else
    {
        //error
        return(0);
    }

    int extensionLength = 0;
    char *endP = name + strlen(name) - 1; //pointer to the last char of filename
    char *temp = endP;

    while (*temp != '.')
    {
        ++extensionLength;
        --temp;
    }

    char *extension = (char *)malloc(sizeof(char)*(extensionLength+1 /* for . */ + 1 /* for null char */));
    strncpy(extension, name+strlen(name)-extensionLength-1, extensionLength+2);

    if(strcmp(extension, ".abc")==0)
    {                
        ++pngs;

        struct images *nextPtr = imagesHeadPtr;

        while(nextPtr->next != NULL)
        nextPtr = nextPtr ->next;

        nextPtr->fileName = (char *)malloc(sizeof(char)*(strlen(name)+1));
        strcpy(nextPtr->fileName, name);
        nextPtr->filePath = (char *)malloc(sizeof(char)*(strlen(dirCopy)+1));
        strcpy(nextPtr->filePath, dirCopy);
        nextPtr->isUsed = 0;
        nextPtr->fileSize = GetFileSize(dirCopy)/1000.0;
        nextPtr->next = (struct images *)malloc(sizeof(struct images));
        nextPtr = nextPtr->next;
        nextPtr->fileName = NULL;
        nextPtr->filePath = NULL;
        nextPtr->isUsed = 0;
        nextPtr->fileSize = 0;
        nextPtr->next = NULL;
    }

    else if(strcmp(extension, ".rst")==0)
    {                
        ++jpgs;

        struct images *nextPtr = imagesHeadPtr;

        while(nextPtr->next != NULL)
        nextPtr = nextPtr ->next;

        nextPtr->fileName = (char *)malloc(sizeof(char)*(strlen(name)+1));
        strcpy(nextPtr->fileName, name);
        nextPtr->filePath = (char *)malloc(sizeof(char)*(strlen(dirCopy)+1));
        strcpy(nextPtr->filePath, dirCopy);
        nextPtr->isUsed = 0;
        nextPtr->fileSize = GetFileSize(dirCopy)/1000.0;
        nextPtr->next = (struct images *)malloc(sizeof(struct images));
        nextPtr = nextPtr->next;
        nextPtr->fileName = NULL;
        nextPtr->filePath = NULL;
        nextPtr->isUsed = 0;
        nextPtr->fileSize = 0;
        nextPtr->next = NULL;
    }

    else if(strcmp(extension, ".dig") == 0)
    {
        ++filesToScan;

        struct filesToParse *nextPtr = filesHeadPtr;

        while(nextPtr->next != NULL)
        nextPtr = nextPtr ->next;

        nextPtr->filePath = (char *)malloc(sizeof(char)*(strlen(dirCopy)+1));
        strcpy(nextPtr->filePath, dirCopy);
        nextPtr->next = (struct filesToParse *)malloc(sizeof(struct filesToParse));
        nextPtr = nextPtr->next;
        nextPtr->filePath = NULL;
        nextPtr->next = NULL;        
    }

    else if(strcmp(extension, ".x") == 0)
    {
        ++filesToScan;

        struct filesToParse *nextPtr = filesHeadPtr;

        while(nextPtr->next != NULL)
        nextPtr = nextPtr ->next;

        nextPtr->filePath = (char *)malloc(sizeof(char)*(strlen(dirCopy)+1));
        strcpy(nextPtr->filePath, dirCopy);
        nextPtr->next = (struct filesToParse *)malloc(sizeof(struct filesToParse));
        nextPtr = nextPtr->next;
        nextPtr->filePath = NULL;
        nextPtr->next = NULL;        
    }

    else if(strcmp(extension, ".cderf") == 0)
    {
        ++filesToScan;

        struct filesToParse *nextPtr = filesHeadPtr;

        while(nextPtr->next != NULL)
        nextPtr = nextPtr ->next;

        nextPtr->filePath = (char *)malloc(sizeof(char)*(strlen(dirCopy)+1));
        strcpy(nextPtr->filePath, dirCopy);
        nextPtr->next = (struct filesToParse *)malloc(sizeof(struct filesToParse));
        nextPtr = nextPtr->next;
        nextPtr->filePath = NULL;
        nextPtr->next = NULL;                        
    } 

        free(extension); //because of this line, my code runs into infinite loop saying
//unable to open dir : too many files open. If I comment this out, my code works fine but the concepts of memory management say that I should be freeing it. 

}

free(tmp);

if (closedir(dir) != 0)
perror("Unable to close directory");

return(1);

}

4

3 に答える 3

3

更新:完全を期すために、別の観測を追加します。

tmp取り扱いも壊れています。1文字のバッファとして割り当てられます。文字列の終了文字には1文字が必要なため、空の文字列以外の有効なC文字列を保持することはできません。

を削除し、直接tmp比較します。ent->d_name

if(strcmp(ent->d_name, ".") == 0)
  continue;

次に、これ:

char *endP = name + strlen(name) - 1; //pointer to the last char of filename
char *temp = endP;

while (*temp != '.')
{
    ++extensionLength;
    --temp;
}

ピリオドを含まないファイル名ではひどく壊れます。

より適切なアプローチは、最後の期間を探し、それが存在しない場合を処理することです。

const char *ldot = strrchr(name, '.');
if(ldot != NULL)
{
  /* Extension found. */
}
else
{
  /* No extension. */
}

もちろん、strrchr()ファイル名がマルチバイトエンコーディングの場合、ファイル名などのライブラリ関数を使用することは安全ではありません。これに注意する必要があります。

于 2012-08-20T11:41:34.663 に答える
2

文字列が異なる場合、または(文字列の終わり)に達すると、 Cライブラリ関数strcmp()は比較を停止します: http ://www.cplusplus.com/reference/clibrary/cstring/strcmp/\0

if(strcmp(tmp, ".") == 0)   //Not valid directories. These are dir's created by system and are hidden.
    continue;

ただし、tmp文字列にはnullターミネータがありません\0。したがって、比較によって無限ループが生成されます。

tmp文字列用に1バイトではなく2バイトを予約します。

char *tmp = malloc(2*sizeof(char));

\0文字列にターミネータを追加します。

tmp[1]='\0';
于 2012-08-20T11:44:42.647 に答える
0

私はすべてのコードを読んだわけではありませんが、おそらくここにバグがあります:

if(strcmp(tmp, ".") == 0)   //Not valid directories. These are dir's created by system and are hidden.
continue;

この構造を使用することにより、除外するだけです。(カレントディレクトリ。したがって、ループの原因となる..(親​​)ディレクトリを除外しているわけではありません。隠されたディレクトリを除外したいので、次の構造を使用するのが最善の方法です。

if (tmp[0] == '.')
于 2012-08-20T11:47:18.207 に答える