1 /*
2 * Copyright (C) 2018 Matthieu Gautier <mgautier@kymeria.fr>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
11 * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
12 * NON-INFRINGEMENT. See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 */
19
20 #include "fs_unix.h"
21 #include <stdexcept>
22
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <dirent.h>
28 #include <errno.h>
29
30 namespace zim
31 {
32
33 namespace unix {
34
readAt(char * dest,zsize_t size,offset_t offset) const35 zsize_t FD::readAt(char* dest, zsize_t size, offset_t offset) const
36 {
37 #if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \
38 defined(__DragonFly__)
39 # define PREAD pread
40 #else
41 # define PREAD pread64
42 #endif
43 ssize_t full_size_read = 0;
44 auto size_to_read = size.v;
45 auto current_offset = offset.v;
46 errno = 0;
47 while (size_to_read > 0) {
48 auto size_read = PREAD(m_fd, dest, size_to_read, current_offset);
49 if (size_read == -1) {
50 return zsize_t(-1);
51 }
52 size_to_read -= size_read;
53 current_offset += size_read;
54 full_size_read += size_read;
55 }
56 return zsize_t(full_size_read);
57 #undef PREAD
58 }
59
getSize() const60 zsize_t FD::getSize() const
61 {
62 struct stat sb;
63 fstat(m_fd, &sb);
64 return zsize_t(sb.st_size);
65 }
66
seek(offset_t offset)67 bool FD::seek(offset_t offset)
68 {
69 return static_cast<int64_t>(offset.v) == lseek(m_fd, offset.v, SEEK_SET);
70 }
71
close()72 bool FD::close() {
73 if (m_fd != -1) {
74 return ::close(m_fd);
75 }
76 return -1;
77 }
78
openFile(path_t filepath)79 FD FS::openFile(path_t filepath)
80 {
81 int fd = open(filepath.c_str(), O_RDONLY);
82 if (fd == -1) {
83 throw std::runtime_error("");
84 }
85 return FD(fd);
86 }
87
makeDirectory(path_t path)88 bool FS::makeDirectory(path_t path)
89 {
90 return !mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
91 }
92
rename(path_t old_path,path_t new_path)93 void FS::rename(path_t old_path, path_t new_path)
94 {
95 ::rename(old_path.c_str(), new_path.c_str());
96 }
97
join(path_t base,path_t name)98 std::string FS::join(path_t base, path_t name)
99 {
100 return base + "/" + name;
101 }
102
remove(path_t path)103 bool FS::remove(path_t path)
104 {
105 DIR* dir;
106 /* It's a directory, remove all its entries first */
107 if ((dir = opendir(path.c_str())) != NULL) {
108 struct dirent* ent;
109 while ((ent = readdir(dir)) != NULL) {
110 std::string childName = ent->d_name;
111 if (childName != "." && childName != "..") {
112 auto childPath = join(path, childName);
113 remove(childPath);
114 }
115 }
116 closedir(dir);
117 return removeDir(path);
118 }
119
120 /* It's a file */
121 else {
122 return removeFile(path);
123 }
124 }
125
removeDir(path_t path)126 bool FS::removeDir(path_t path) {
127 return rmdir(path.c_str());
128 }
129
removeFile(path_t path)130 bool FS::removeFile(path_t path) {
131 return ::remove(path.c_str());
132 }
133
134
135 }; // unix namespace
136
137 }; // zim namespace
138
139