213 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
#include "fs.h"
 | 
						|
#include "files.h"
 | 
						|
#include <unistd.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/wait.h>
 | 
						|
#include <dirent.h>
 | 
						|
#include <string>
 | 
						|
#include <vector>
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
#include <errno.h>
 | 
						|
#include <sys/stat.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <string.h>
 | 
						|
#include <host/CopyFile.h>
 | 
						|
 | 
						|
using namespace std;
 | 
						|
 | 
						|
static bool
 | 
						|
is_dir(const string& path)
 | 
						|
{
 | 
						|
    int err;
 | 
						|
    struct stat st;
 | 
						|
    err = stat(path.c_str(), &st);
 | 
						|
    return err != 0 || S_ISDIR(st.st_mode);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
remove_file(const string& path)
 | 
						|
{
 | 
						|
    int err = unlink(path.c_str());
 | 
						|
    if (err != 0) {
 | 
						|
        fprintf(stderr, "error deleting file %s (%s)\n", path.c_str(),
 | 
						|
                strerror(errno));
 | 
						|
        return errno;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
remove_recursively(const string& path)
 | 
						|
{
 | 
						|
    int err;
 | 
						|
 | 
						|
    if (is_dir(path)) {
 | 
						|
        DIR *d = opendir(path.c_str());
 | 
						|
        if (d == NULL) {
 | 
						|
            fprintf(stderr, "error getting directory contents %s (%s)\n",
 | 
						|
                    path.c_str(), strerror(errno));
 | 
						|
            return errno;
 | 
						|
        }
 | 
						|
 | 
						|
        vector<string> files;
 | 
						|
        vector<string> dirs;
 | 
						|
 | 
						|
        struct dirent *ent;
 | 
						|
        while (NULL != (ent = readdir(d))) {
 | 
						|
            if (0 == strcmp(".", ent->d_name)
 | 
						|
                    || 0 == strcmp("..", ent->d_name)) {
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            string full = path;
 | 
						|
            full += '/';
 | 
						|
            full += ent->d_name;
 | 
						|
            bool is_directory = (ent->d_type == DT_DIR);
 | 
						|
            if (is_directory) {
 | 
						|
                dirs.push_back(full);
 | 
						|
            } else {
 | 
						|
                files.push_back(full);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        closedir(d);
 | 
						|
 | 
						|
        for (vector<string>::iterator it=files.begin(); it!=files.end(); it++) {
 | 
						|
            err = remove_file(*it);
 | 
						|
            if (err != 0) {
 | 
						|
                return err;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        for (vector<string>::iterator it=dirs.begin(); it!=dirs.end(); it++) {
 | 
						|
            err = remove_recursively(*it);
 | 
						|
            if (err != 0) {
 | 
						|
                return err;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        err = rmdir(path.c_str());
 | 
						|
        if (err != 0) {
 | 
						|
            fprintf(stderr, "error deleting directory %s (%s)\n", path.c_str(),
 | 
						|
                    strerror(errno));
 | 
						|
            return errno;
 | 
						|
        }
 | 
						|
        return 0;
 | 
						|
    } else {
 | 
						|
        return remove_file(path);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
mkdir_recursively(const string& path)
 | 
						|
{
 | 
						|
    int err;
 | 
						|
    size_t pos = 0;
 | 
						|
    // For absolute pathnames, that starts with leading '/'
 | 
						|
    // use appropriate initial value.
 | 
						|
    if (path.length() != 0 and path[0] == '/') pos++;
 | 
						|
 | 
						|
    while (true) {
 | 
						|
        pos = path.find('/', pos);
 | 
						|
        string p = path.substr(0, pos);
 | 
						|
        struct stat st;
 | 
						|
        err = stat(p.c_str(), &st);
 | 
						|
        if (err != 0) {
 | 
						|
            err = mkdir(p.c_str(), 0770);
 | 
						|
            if (err != 0) {
 | 
						|
                fprintf(stderr, "can't create directory %s (%s)\n",
 | 
						|
                        path.c_str(), strerror(errno));
 | 
						|
                return errno;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else if (!S_ISDIR(st.st_mode)) {
 | 
						|
            fprintf(stderr, "can't create directory %s because %s is a file.\n",
 | 
						|
                        path.c_str(), p.c_str());
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
        pos++;
 | 
						|
        if (p == path) {
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
copy_file(const string& src, const string& dst)
 | 
						|
{
 | 
						|
    int err;
 | 
						|
 | 
						|
    err = copyFile(src.c_str(), dst.c_str(),
 | 
						|
                    COPY_NO_DEREFERENCE | COPY_FORCE | COPY_PERMISSIONS);
 | 
						|
    return err;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
strip_file(const string& path)
 | 
						|
{
 | 
						|
    // Default strip command to run is "strip" unless overridden by the ATREE_STRIP env var.
 | 
						|
    const char* strip_cmd = getenv("ATREE_STRIP");
 | 
						|
    if (!strip_cmd || !strip_cmd[0]) {
 | 
						|
        strip_cmd = "strip";
 | 
						|
    }
 | 
						|
    pid_t pid = fork();
 | 
						|
    if (pid == -1) {
 | 
						|
        // Fork failed. errno should be set.
 | 
						|
        return -1;
 | 
						|
    } else if (pid == 0) {
 | 
						|
        // Exec in the child. Only returns if execve failed.
 | 
						|
 | 
						|
        int num_args = 0;
 | 
						|
        const char *s = strip_cmd;
 | 
						|
        while (*s) {
 | 
						|
            while (*s == ' ') ++s;
 | 
						|
            if (*s && *s != ' ') {
 | 
						|
                ++num_args;
 | 
						|
                while (*s && *s != ' ') ++s;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (num_args <= 0) {
 | 
						|
            fprintf(stderr, "Invalid ATREE_STRIP command '%s'\n", strip_cmd);
 | 
						|
            return 1;
 | 
						|
 | 
						|
        } else if (num_args == 1) {
 | 
						|
            return execlp(strip_cmd, strip_cmd, path.c_str(), (char *)NULL);
 | 
						|
 | 
						|
        } else {
 | 
						|
            // Split the arguments if more than 1
 | 
						|
            char* cmd = strdup(strip_cmd);
 | 
						|
            const char** args = (const char**) malloc(sizeof(const char*) * (num_args + 2));
 | 
						|
 | 
						|
            const char** curr = args;
 | 
						|
            char* s = cmd;
 | 
						|
            while (*s) {
 | 
						|
                while (*s == ' ') ++s;
 | 
						|
                if (*s && *s != ' ') {
 | 
						|
                    *curr = s;
 | 
						|
                    ++curr;
 | 
						|
                    while (*s && *s != ' ') ++s;
 | 
						|
                    if (*s) {
 | 
						|
                        *s = '\0';
 | 
						|
                        ++s;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            args[num_args] = path.c_str();
 | 
						|
            args[num_args + 1] = NULL;
 | 
						|
 | 
						|
            int ret = execvp(args[0], (char* const*)args);
 | 
						|
            free(args);
 | 
						|
            free(cmd);
 | 
						|
            return ret;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        // Wait for child pid and return its exit code.
 | 
						|
        int status;
 | 
						|
        waitpid(pid, &status, 0);
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
}
 | 
						|
 |