forked from maxLundin/os-find
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f2bf5d2
commit b259fb3
Showing
14 changed files
with
774 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
CMakeLists.txt.user | ||
cmake-build-debug | ||
.directory | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
cmake_minimum_required(VERSION 3.1) | ||
|
||
set(CMAKE_CXX_STANDARD 14) | ||
|
||
project(find) | ||
|
||
add_executable(find find.cpp | ||
actor.cpp | ||
actor.h | ||
environment.cpp | ||
environment.h | ||
platform.h | ||
programconditions.cpp | ||
programconditions.h | ||
query.cpp | ||
query.h) | ||
|
||
install(TARGETS find | ||
RUNTIME DESTINATION bin) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
MIT License | ||
|
||
Copyright (c) 2019 Ilya Bizyaev | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,31 @@ | ||
# Необходимо написать подмножество утилиты find. | ||
|
||
## Программа должна: | ||
|
||
- Первым аргументом принимать абсолютный путь, в котором будет производиться поиск файлов. | ||
- По-умолчанию выводить в стандартный поток вывода все найденные файлы по этому пути | ||
- Поддерживать аргумент -inum num. Аргумент задает номер инода | ||
- Поддерживать аргумент -name name. Аргумент задает имя файла | ||
- Поддерживать аргумент -size [-=+]size. Аргумент задает фильтр файлов по размеру(меньше, равен, больше) | ||
- Поддерживать аргумент -nlinks num. Аргумент задает количество hardlink'ов у файлов | ||
- Поддерживать аргумент -exec path. Аргумент задает путь до исполняемого файла, которому в качестве единственного аргумент нужно передать найденный в иерархии файл | ||
- Поддерживать комбинацию аргументов. Например хочется найти все файлы с размером больше 1GB и скормить их утилите /usr/bin/sha1sum. | ||
- Выполнять поиск рекурсивно, в том числе во всех вложенных директориях. | ||
- Сильные духом призываются к выполнению задания с использованием системного вызова getdents(2). Остальные могут использовать readdir и opendir для чтения содержимого директории. | ||
# find - a basic file search utility | ||
|
||
## Goal | ||
This is an educational project, aimed at understanding how to interact with | ||
POSIX and Linux-specific APIs to retrieve file information. | ||
|
||
## Features: | ||
* Filter by wildcards, size ranges, inodes and link counts | ||
* Print search results to stdout or pass to an executable | ||
|
||
## Building | ||
``` | ||
$ mkdir build | ||
$ cd build | ||
$ cmake .. | ||
$ make | ||
``` | ||
|
||
Requires a C++14 compiler. | ||
|
||
## Usage | ||
Please refer to `find --help` for details. | ||
|
||
## Testing | ||
Tested by hand on Linux 4.12. | ||
|
||
## Copyright | ||
Ilya Bizyaev, 2019 (<[email protected]>) | ||
|
||
Licensed under MIT terms. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#include <sys/types.h> | ||
#include <sys/wait.h> | ||
#include <unistd.h> | ||
|
||
#include <iostream> | ||
|
||
#include "actor.h" | ||
#include "programconditions.h" | ||
|
||
int execute_program(const std::string& path, | ||
const std::vector<std::string>& args, | ||
const std::map<std::string, std::string>& env) | ||
{ | ||
pid_t pid = fork(); | ||
if (!pid) { | ||
// We are a child | ||
ProgramConditions conditions(args, env); | ||
execve(path.c_str(), conditions.get_argv(), conditions.get_envp()); | ||
// This code will only execute if execve has failed | ||
std::cerr << "Failed to execute the program: " << strerror(errno) << std::endl; | ||
exit(EXIT_FAILURE); | ||
} else if (pid > 0) { | ||
// We are a parent | ||
int status; | ||
pid_t result = waitpid(pid, &status, 0); | ||
if (result > 0) { | ||
if (WIFEXITED(status)) { | ||
// terminated normally | ||
int exit_code = WEXITSTATUS(status); | ||
return exit_code; | ||
} else { // WIFSIGNALED(status) | ||
// terminated due to an uncaught signal | ||
int signal_number = WTERMSIG(status); | ||
return -signal_number; | ||
} | ||
} else { | ||
// Process wait failure | ||
std::error_code ec(errno, std::system_category()); | ||
throw std::system_error(ec, "Failed to wait for child return"); | ||
} | ||
} else { | ||
// Fork failure | ||
std::error_code ec(errno, std::system_category()); | ||
throw std::system_error(ec, "Failed to spawn child process"); | ||
} | ||
} | ||
|
||
void Actor::set_executable(const std::string &executable) | ||
{ | ||
m_args = { executable }; | ||
} | ||
|
||
void Actor::process(const std::string &filename) | ||
{ | ||
if (m_args.empty()) { | ||
std::cout << filename << std::endl; | ||
} else { | ||
m_args.push_back(filename); | ||
} | ||
} | ||
|
||
void Actor::submit(const std::map<std::string, std::string> &env) | ||
{ | ||
if (!m_args.empty()) { | ||
execute_program(m_args.front(), m_args, env); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#ifndef ACTOR_H | ||
#define ACTOR_H | ||
|
||
#include <string.h> | ||
#include <vector> | ||
#include <map> | ||
|
||
/*! | ||
* Manages actions for located files | ||
* By default, prints file list to stdout | ||
*/ | ||
class Actor | ||
{ | ||
public: | ||
Actor() = default; | ||
|
||
void set_executable(const std::string& executable); | ||
void process(const std::string& filename); | ||
void submit(const std::map<std::string, std::string>& env); | ||
private: | ||
std::vector<std::string> m_args; | ||
}; | ||
|
||
#endif // ACTOR_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#include <unistd.h> | ||
|
||
#include <sstream> | ||
|
||
#include "environment.h" | ||
|
||
Environment::Environment(char *envp[]) | ||
{ | ||
for (; *envp != nullptr; ++envp) { | ||
set_variable(std::string(*envp)); | ||
} | ||
if (m_environ.find("PATH") == m_environ.end()) { | ||
// Assuming default value for LSB | ||
set_variable("PATH=/bin:/sbin:/usr/bin:/usr/sbin"); | ||
} | ||
} | ||
|
||
void Environment::update_paths(const std::string& path_value) | ||
{ | ||
m_paths.clear(); | ||
std::stringstream ss(path_value); | ||
|
||
std::string segment; | ||
while (std::getline(ss, segment, ':')) | ||
{ | ||
m_paths.push_back(segment); | ||
} | ||
} | ||
|
||
void Environment::set_variable(const std::string& assignment) | ||
{ | ||
size_t eq = assignment.find('='); | ||
std::string key, value; | ||
if (eq != std::string::npos) { | ||
key = assignment.substr(0, eq); | ||
value = assignment.substr(eq + 1); | ||
} else { | ||
key = assignment; | ||
value = ""; | ||
} | ||
|
||
m_environ[key] = value; | ||
if (key == "PATH") { | ||
update_paths(value); | ||
} | ||
} | ||
|
||
void Environment::unset_variable(const std::string& var) | ||
{ | ||
m_environ.erase(var); | ||
} | ||
|
||
const std::map<std::string, std::string>& Environment::get_variables() | ||
{ | ||
return m_environ; | ||
} | ||
|
||
std::string Environment::find_executable(const std::string& filename) const | ||
{ | ||
if (executable_exists(filename)) { | ||
return filename; | ||
} | ||
for (const auto& prefix : m_paths) { | ||
std::string attempt = prefix + "/" + filename; | ||
if (executable_exists(attempt)) { | ||
return attempt; | ||
} | ||
} | ||
return ""; | ||
} | ||
|
||
bool Environment::executable_exists(const std::string &filename) const | ||
{ | ||
return access(filename.c_str(), X_OK) != -1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#ifndef ENVIRONMENT_H | ||
#define ENVIRONMENT_H | ||
|
||
#include <map> | ||
#include <string> | ||
#include <vector> | ||
|
||
/*! | ||
* Manages shell environment variables | ||
* For PATH, keeps an up-to-date searchable paths list | ||
*/ | ||
class Environment | ||
{ | ||
public: | ||
explicit Environment(char *envp[]); | ||
|
||
void update_paths(const std::string& path_value); | ||
void set_variable(const std::string& assignment); | ||
void unset_variable(const std::string& var); | ||
const std::map<std::string, std::string>& get_variables(); | ||
std::string find_executable(const std::string& filename) const; | ||
private: | ||
bool executable_exists(const std::string& filename) const; | ||
|
||
std::map<std::string, std::string> m_environ; | ||
std::vector<std::string> m_paths; | ||
}; | ||
|
||
#endif // ENVIRONMENT_H |
Oops, something went wrong.