1 /*
2 +----------------------------------------------------------------------+
3 | Swoole |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 2.0 of the Apache license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | http://www.apache.org/licenses/LICENSE-2.0.html |
9 | If you did not receive a copy of the Apache2.0 license and are unable|
10 | to obtain it through the world-wide-web, please send a note to |
11 | license@swoole.com so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Tianfeng Han <mikan.tenny@gmail.com> |
14 +----------------------------------------------------------------------+
15 */
16
17 #include "swoole_file.h"
18
swoole_tmpfile(char * filename)19 int swoole_tmpfile(char *filename) {
20 #if defined(HAVE_MKOSTEMP) && defined(HAVE_EPOLL)
21 int tmp_fd = mkostemp(filename, O_WRONLY | O_CREAT);
22 #else
23 int tmp_fd = mkstemp(filename);
24 #endif
25
26 if (tmp_fd < 0) {
27 swoole_sys_warning("mkstemp(%s) failed", filename);
28 return SW_ERR;
29 } else {
30 return tmp_fd;
31 }
32 }
33
34 namespace swoole {
35
file_get_size(FILE * fp)36 ssize_t file_get_size(FILE *fp) {
37 fflush(fp);
38 return file_get_size(fileno(fp));
39 }
40
file_get_size(const std::string & filename)41 ssize_t file_get_size(const std::string &filename) {
42 File file(filename, File::READ);
43 if (!file.ready()) {
44 swoole_set_last_error(errno);
45 return -1;
46 }
47 return file.get_size();
48 }
49
file_get_size(int fd)50 ssize_t file_get_size(int fd) {
51 FileStatus file_stat;
52 if (fstat(fd, &file_stat) < 0) {
53 swoole_set_last_error(errno);
54 return -1;
55 }
56 if (!S_ISREG(file_stat.st_mode)) {
57 swoole_set_last_error(EISDIR);
58 return -1;
59 }
60 return file_stat.st_size;
61 }
62
file_get_contents(const std::string & filename)63 std::shared_ptr<String> file_get_contents(const std::string &filename) {
64 File fp(filename, O_RDONLY);
65 if (!fp.ready()) {
66 swoole_sys_warning("open(%s) failed", filename.c_str());
67 return nullptr;
68 }
69
70 ssize_t filesize = fp.get_size();
71 if (filesize < 0) {
72 return nullptr;
73 } else if (filesize == 0) {
74 swoole_error_log(SW_LOG_TRACE, SW_ERROR_FILE_EMPTY, "file[%s] is empty", filename.c_str());
75 return nullptr;
76 } else if (filesize > SW_MAX_FILE_CONTENT) {
77 swoole_error_log(SW_LOG_WARNING, SW_ERROR_FILE_TOO_LARGE, "file[%s] is too large", filename.c_str());
78 return nullptr;
79 }
80
81 std::shared_ptr<String> content = std::make_shared<String>(filesize + 1);
82 ssize_t read_bytes = fp.read_all(content->str, filesize);
83 content->length = read_bytes;
84 content->str[read_bytes] = '\0';
85 return content;
86 }
87
make_tmpfile()88 File make_tmpfile() {
89 char *tmpfile = sw_tg_buffer()->str;
90 size_t l = swoole_strlcpy(tmpfile, SwooleG.task_tmpfile.c_str(), SW_TASK_TMP_PATH_SIZE);
91 int tmp_fd = swoole_tmpfile(tmpfile);
92 if (tmp_fd < 0) {
93 return File(-1);
94 } else {
95 return File(tmp_fd, std::string(tmpfile, l));
96 }
97 }
98
file_put_contents(const std::string & filename,const char * content,size_t length)99 bool file_put_contents(const std::string &filename, const char *content, size_t length) {
100 if (length <= 0) {
101 swoole_error_log(SW_LOG_TRACE, SW_ERROR_FILE_EMPTY, "content is empty");
102 return false;
103 }
104 if (length > SW_MAX_FILE_CONTENT) {
105 swoole_error_log(SW_LOG_WARNING, SW_ERROR_FILE_TOO_LARGE, "content is too large");
106 return false;
107 }
108 File file(filename, O_WRONLY | O_TRUNC | O_CREAT, 0666);
109 if (!file.ready()) {
110 swoole_sys_warning("open(%s) failed", filename.c_str());
111 return false;
112 }
113 return file.write_all(content, length);
114 }
115
write_all(const void * data,size_t len)116 size_t File::write_all(const void *data, size_t len) {
117 size_t written_bytes = 0;
118 while (written_bytes < len) {
119 ssize_t n;
120 if (flags_ & APPEND) {
121 n = write((char *) data + written_bytes, len - written_bytes);
122 } else {
123 n = pwrite((char *) data + written_bytes, len - written_bytes, written_bytes);
124 }
125 if (n > 0) {
126 written_bytes += n;
127 } else if (n == 0) {
128 break;
129 } else {
130 if (errno == EINTR) {
131 continue;
132 } else if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
133 swoole_sys_warning("pwrite(%d, %p, %lu, %lu) failed", fd_, data, len - written_bytes, written_bytes);
134 }
135 break;
136 }
137 }
138 return written_bytes;
139 }
140
read_all(void * buf,size_t len)141 size_t File::read_all(void *buf, size_t len) {
142 size_t read_bytes = 0;
143 while (read_bytes < len) {
144 ssize_t n = pread((char *) buf + read_bytes, len - read_bytes, read_bytes);
145 if (n > 0) {
146 read_bytes += n;
147 } else if (n == 0) {
148 break;
149 } else {
150 if (errno == EINTR) {
151 continue;
152 } else if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
153 swoole_sys_warning("pread(%d, %p, %lu, %lu) failed", fd_, buf, len - read_bytes, read_bytes);
154 }
155 break;
156 }
157 }
158 return read_bytes;
159 }
160
read_content()161 std::shared_ptr<String> File::read_content() {
162 ssize_t n = 0;
163 std::shared_ptr<String> data = std::make_shared<String>(SW_BUFFER_SIZE_STD);
164 while (1) {
165 n = read(data->str + data->length, data->size - data->length);
166 if (n <= 0) {
167 return data;
168 } else {
169 if (!data->grow((size_t) n)) {
170 return data;
171 }
172 }
173 }
174 return data;
175 }
176
177 } // namespace swoole
178