1 /* (PD) 2001 The Bitzi Corporation
2  * Please see file COPYING or http://bitzi.com/publicdomain
3  * for more info.
4  *
5  * $Id: dirsearch.c,v 1.4 2001/06/16 03:28:43 mayhemchaos Exp $
6  */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "bitcollider.h"
11 #include "dirsearch.h"
12 
13 #ifdef _WIN32
14 #include <windows.h>
15 #else
16 #include <sys/stat.h>
17 #include <unistd.h>
18 #include <sys/types.h>
19 #include <dirent.h>
20 #endif
21 
22 #ifndef WIN32
23 // check the type and do the long name lookup on the file
check_file_type(const char * path)24 FileType check_file_type(const char *path)
25 {
26    struct stat sbuf;
27 
28    if (lstat(path, &sbuf) == 0)
29    {
30        if (S_ISCHR(sbuf.st_mode) || S_ISBLK(sbuf.st_mode) ||
31            S_ISFIFO(sbuf.st_mode) || S_ISSOCK(sbuf.st_mode))
32           return eOther;
33 
34        if (S_ISREG(sbuf.st_mode))
35           return eFile;
36        else
37        if (S_ISDIR(sbuf.st_mode) && !S_ISLNK(sbuf.st_mode))
38           return eDir;
39        else
40           return eOther;
41    }
42    else
43        return eNotFound;
44 }
45 
recurse_dir(BitcolliderSubmission * sub,const char * path,b_bool analyzeAll,b_bool recurseDeep)46 int  recurse_dir(BitcolliderSubmission *sub,
47                  const char *path,
48                  b_bool analyzeAll,
49                  b_bool recurseDeep)
50 {
51    DIR           *dir;
52    struct dirent *entry;
53    char           newPath[MAX_PATH];
54    int            count = 0;
55    struct stat    sbuf;
56 
57    dir = opendir(path);
58    if (dir == NULL)
59    {
60        return 0;
61    }
62 
63    for(;;)
64    {
65        if (sub->bc->exitNow)
66            break;
67 
68        /* Scan the given dir for plugins */
69        entry = readdir(dir);
70        if (!entry)
71           break;
72 
73        /* Skip the . and .. dirs */
74        if (strcmp(entry->d_name, ".") == 0 ||
75            strcmp(entry->d_name, "..") == 0)
76           continue;
77 
78        sprintf(newPath, "%s/%s", path, entry->d_name);
79        if (lstat(newPath, &sbuf) == 0)
80        {
81            if (S_ISDIR(sbuf.st_mode) && !S_ISLNK(sbuf.st_mode) && recurseDeep)
82            {
83                count += recurse_dir(sub, newPath, analyzeAll, recurseDeep);
84            }
85            else
86            if (S_ISREG(sbuf.st_mode))
87            {
88                fflush(stdout);
89 
90                if (analyze_file(sub, newPath, !analyzeAll))
91                {
92                   count++;
93                }
94            }
95            else
96            {
97                if (sub->bc->progressCallback)
98                   sub->bc->progressCallback(0, newPath,
99                              "skipped. (not a regular file)");
100            }
101        }
102    }
103    closedir(dir);
104 
105    return count;
106 }
107 
108 #else
109 
110 // check the type and do the long name lookup on the file
check_file_type(const char * path)111 FileType check_file_type(const char *path)
112 {
113    DWORD type;
114 
115    type = (int)GetFileAttributes(path);
116    if ((int)type < 0)
117       return eNotFound;
118 
119    if (type & FILE_ATTRIBUTE_DIRECTORY)
120       return eDir;
121 
122    if ((type & FILE_ATTRIBUTE_HIDDEN) ||
123        (type & FILE_ATTRIBUTE_OFFLINE) ||
124        (type & FILE_ATTRIBUTE_TEMPORARY))
125       return eOther;
126 
127    return eFile;
128 }
129 
recurse_dir(BitcolliderSubmission * sub,const char * path,b_bool analyzeAll,b_bool recurseDeep)130 int recurse_dir(BitcolliderSubmission *sub,
131                 const char *path,
132                 b_bool analyzeAll,
133                 b_bool recurseDeep)
134 {
135    WIN32_FIND_DATA  find;
136    HANDLE           hFind;
137    int              count = 0, j;
138    char             newPath[MAX_PATH], newFile[MAX_PATH], savedPath[MAX_PATH];
139    FileType         type;
140 
141    strcpy(newPath, path);
142    if (newPath[strlen(newPath) - 1] == '\\')
143       newPath[strlen(newPath) - 1] = 0;
144 
145    strcpy(savedPath, newPath);
146 
147    /* if a path was specified, then add a \*.* */
148    if ((GetFileAttributes(newPath) & FILE_ATTRIBUTE_DIRECTORY) != 0)
149       strcat(newPath, "\\*.*");
150 
151    hFind = FindFirstFile(newPath, &find);
152    if (hFind == INVALID_HANDLE_VALUE)
153       return -1;
154 
155    /* If its not a directory, then remove everything after the last slash */
156    if ((GetFileAttributes(savedPath) & FILE_ATTRIBUTE_DIRECTORY) == 0)
157    {
158       char *ptr;
159 
160       ptr = strrchr(savedPath, '\\');
161       if (ptr)
162          *ptr = 0;
163    }
164 
165    for(j = 0;; j++)
166    {
167        if (sub->bc->exitNow)
168            break;
169 
170        if (j > 0)
171           if (!FindNextFile(hFind, &find))
172               break;
173 
174        /* Skip the . and .. dirs */
175        if (strcmp(find.cFileName, ".") == 0 ||
176            strcmp(find.cFileName, "..") == 0)
177           continue;
178 
179        sprintf(newPath, "%s\\%s", savedPath, find.cFileName);
180        type = check_file_type(newPath);
181        if (type == eDir && recurseDeep)
182        {
183           count += recurse_dir(sub, newPath, analyzeAll, recurseDeep);
184        }
185        if (type == eFile)
186        {
187           getLongPathName(newPath, MAX_PATH, newFile);
188           if (analyze_file(sub, newFile, !analyzeAll))
189              count++;
190        }
191        else
192        {
193           if (sub->bc->progressCallback)
194              sub->bc->progressCallback(0, newPath,
195                          "skipped. (not a regular file)");
196        }
197    }
198    FindClose(hFind);
199 
200    return count;
201 
202 }
203 
204 #endif
205