Repository navigation
Expand file tree
/
Copy pathmain.cpp
More file actions
157 lines (127 loc) · 4.68 KB
/
Copy pathmain.cpp
File metadata and controls
157 lines (127 loc) · 4.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <iostream>
#include <vector>
#include <unistd.h>
#include <string>
#include <dirent.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <algorithm>
std::string str_tolower(std::string s) {
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c){ return std::tolower(c); }
);
// debug
// printf("converted %s\n",s.c_str());
return s;
}
void findFileInDir(std::string searchPath, std::string searchTerm, bool caseInsensitive, bool recursive)
{
struct dirent* dirent_ptr;
struct stat statbuf;
DIR* dir_ptr;
// open dir or return if unsuccessful
if ((dir_ptr = opendir(searchPath.c_str())) == NULL){
return;
}
// read dir and loop over all elements inside folder
while ((dirent_ptr = readdir(dir_ptr)) != NULL) {
std::string fileName = dirent_ptr->d_name;
// these two elements can be skipped
if(fileName.compare(".") == 0 || fileName.compare("..") == 0)
continue;
// check if searchterm matches current element in folder.
// also call function str_tolower if the option case insensitive is turned on
if(searchTerm.compare(caseInsensitive ? str_tolower(fileName) : fileName) == 0){
printf("[%d]: %s: %s\n",getpid(), searchTerm.c_str(),realpath(searchPath.c_str(),0));
return;
}
// if recursion is turned on
if(recursive){
std::string fullSearchPath = searchPath + "/" + fileName;
// create statbuf to check if element is a directory
if(stat(fullSearchPath.c_str(),&statbuf) == -1){
printf("ERROR!");
return;
}
// check if file is directory
if(S_ISDIR(statbuf.st_mode)){
// search element if it is a directory
findFileInDir(fullSearchPath, searchTerm,caseInsensitive,recursive);
// debug
// printf("%s is dir\n", fileName.c_str());
}
}
// debug
// printf("dir: %s - term: %s\n", fileName.c_str(), searchTerm.c_str());
}
closedir(dir_ptr);
}
//
// A child proccess is forked for every search term a user has inputed. Then the function findFileInDir(), which opens the current folder and
// loops through every file inside this folder. If the current file is a folder the function findFileInDir() is called with this new search path
// If the search term of this process matches the current file which is being looped over, then the console outputs a success message
//
int main(int argc, char* argv[])
{
int c, optionCount = 1;
bool optionIsRecursive = false, optionIsCaseInsensitive = false;
// check if any options were given
while((c = getopt(argc, argv, "Ri")) != EOF) {
switch(c) {
case 'i':
optionCount++;
optionIsCaseInsensitive = true;
std::cout << "[-i] enabled" << std::endl;
break;
case 'R':
optionCount++;
optionIsRecursive = true;
std::cout << "[-R] enabled" << std::endl;
break;
default:
std::cout << "Something is extremly wrong!" << std::endl;
break;
}
}
std::string searchPath = argv[optionCount];
std::cout << "SearchPath: " << searchPath << std::endl;
std::vector<std::string> searchTerms;
for(int i = 0; i < argc-optionCount-1; i++) {
searchTerms.push_back(argv[optionCount+i+1]);
std::cout << "Term " << i << ": " << searchTerms[i] << std::endl;
}
pid_t pid;
int i;
// fork for every searchTerm
for(i = 0; i < (int) searchTerms.size(); i++) {
pid = fork();
// get i search element
std::string searchTerm = searchTerms[i];
if(optionIsCaseInsensitive)
searchTerm = str_tolower(searchTerm);
switch(pid) {
case -1:
return EXIT_FAILURE;
case 0:
// CHILD PROCESS
// start find for i search term
findFileInDir(searchPath,searchTerm,optionIsCaseInsensitive,optionIsRecursive);
return EXIT_SUCCESS;
break;
default:
// PARENT PROCESS
break;
}
}
// prevent zombie processes
pid_t childpid;
while((childpid = waitpid(-1,NULL,WNOHANG))){
if((childpid == -1) && (errno != EINTR)){
break;
}
}
// wait for all processes
for(i = 0; i < (int) searchTerms.size(); i++)
wait(NULL);
return EXIT_SUCCESS;
}