| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "spec_utils.h" |
| #include <dirent.h> |
| #include <errno.h> |
| #include <glog/logging.h> |
| #include <limits.h> |
| #include <string> |
| #include <sys/stat.h> |
| #include <sys/stat.h> |
| #include <sys/time.h> |
| #include <sys/types.h> |
| #include <time.h> |
| #include <unistd.h> |
| |
| int DeleteDir(std::string dirname) { |
| DLOG(INFO) << "Deleting: " << dirname; |
| DIR* dir = opendir(dirname.c_str()); |
| if (dir == NULL) { |
| return errno; |
| } |
| |
| struct dirent* de; |
| struct stat stat_buf; |
| while ((de = readdir(dir)) != NULL) { |
| if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { |
| continue; |
| } |
| |
| std::string name = dirname + "/" + de->d_name; |
| if (stat(name.c_str(), &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode)) { |
| if (DeleteDir(name) != 0) { |
| return errno; |
| } |
| } else { |
| if (unlink(name.c_str()) != 0) { |
| return errno; |
| } |
| } |
| } |
| |
| if (closedir(dir) != 0) { |
| return errno; |
| } |
| if (rmdir(dirname.c_str()) != 0) { |
| return errno; |
| } |
| return 0; |
| } |
| |
| int CopyDir(std::string dest_dirname, std::string src_dirname) { |
| DIR* dir = opendir(src_dirname.c_str()); |
| if (dir == NULL) { |
| return errno; |
| } |
| |
| DLOG(INFO) << "Copy " << src_dirname << " to " << dest_dirname; |
| struct dirent* de; |
| struct stat stat_buf; |
| while ((de = readdir(dir)) != NULL) { |
| std::string name = src_dirname + "/" + de->d_name; |
| if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { |
| continue; |
| } |
| |
| if (stat(name.c_str(), &stat_buf) != 0) { |
| return errno; |
| } |
| if (S_ISDIR(stat_buf.st_mode)) { |
| std::string sub_dir = dest_dirname + "/" + de->d_name; |
| if (mkdir(sub_dir.c_str(), 0600) != 0) { |
| return errno; |
| } |
| if (CopyDir(sub_dir, name) != 0) { |
| return errno; |
| } |
| } else if (S_ISREG(stat_buf.st_mode)) { |
| if (CopyFile(dest_dirname + "/" + de->d_name, name) != 0) { |
| return errno; |
| } |
| } |
| } |
| if (closedir(dir) != 0) { |
| return errno; |
| } |
| return 0; |
| } |
| |
| int CopyFile(std::string dest, std::string src) { |
| int page_size = getpagesize(); |
| char buf[page_size]; |
| size_t size; |
| DLOG(INFO) << "Copy " << src << " to " << dest; |
| FILE* srcfile = fopen(src.c_str(), "rb"); |
| if (srcfile == NULL) { |
| return errno; |
| } |
| FILE* destfile = fopen(dest.c_str(), "wb"); |
| if (destfile == NULL) { |
| return errno; |
| } |
| |
| while ((size = fread(buf, 1, page_size, srcfile))) { |
| if (fwrite(buf, 1, size, destfile) != size) { |
| return errno; |
| } |
| } |
| |
| if (fclose(srcfile) != 0) { |
| return errno; |
| } |
| if (fflush(destfile) != 0) { |
| return errno; |
| } |
| if (fclose(destfile) != 0) { |
| return errno; |
| } |
| return 0; |
| } |