MCS: Use remote.h and cleanup header file inclusion
[remote/remote-mci.git] / libutil / File.cc
blob3354baa63331ec2cb90089b68be55a572b8e1da1
1 #include <unistd.h>
2 #include <stdio.h>
3 #include <fcntl.h>
4 #include <errno.h>
5 #include <libgen.h>
7 #include "libutil/File.h"
8 #include "libutil/Log.h"
10 namespace remote { namespace util {
12 std::string File::readFile(std::string filename)
14 char buffer[1024];
15 ssize_t size, i;
16 int fd;
18 fd = open(filename.c_str(), O_RDONLY | O_NONBLOCK);
19 if (fd < 0) {
20 Log::error("open(%s) failed: %s", filename.c_str(), strerror(errno));
21 return std::string("");
24 do {
25 size = read(fd, buffer, sizeof(buffer) - 1);
26 } while ((size < 0) && (errno == EAGAIN || errno == EINTR));
28 if (size == -1) {
29 Log::error("read(%s) failed: %s", filename.c_str(), strerror(errno));
30 size = 0;
33 /* Non-blocking, so we should have the full contents now. */
34 close(fd);
36 /* Sanitize the string to only hold sane ASCII characters. */
37 for (i = size - 1; i >= 0; i--) {
38 int c = buffer[i];
40 if (c <= ' ' || c > 126) {
41 /* Discard cruft at the end. */
42 if (i + 1 == size) {
43 size--;
44 continue;
47 c = '_';
48 } else if (c == '\'' || c == '"' || c == '\\') {
49 c = '_';
52 buffer[i] = c;
54 buffer[size] = 0;
56 return std::string(buffer);
59 std::string File::readLink(std::string linkname)
61 std::string filename;
62 char buf[PATH_MAX];
63 ssize_t buflen;
64 int relative = 0;
66 buflen = readlink(linkname.c_str(), buf, sizeof(buf));
67 if (buflen == -1) {
68 Log::error("readlink(%s) failed: %s", linkname.c_str(), strerror(errno));
69 return std::string("");
72 buf[buflen] = 0;
73 filename = buf;
75 while (filename.substr(0, 3) == "../") {
76 filename.erase(0, 3);
77 relative++;
80 if (!relative)
81 return filename;
83 if (linkname.size() >= sizeof(buf)) {
84 Log::error("Link name too long: %s", linkname.c_str());
85 return std::string("");
88 linkname.copy(buf, linkname.size());
90 dirname(buf);
91 while (relative--);
93 filename.insert(0, "/");
94 filename.insert(0, buf);
96 return filename;
99 bool File::writeFile(std::string filename, const void *data, uint32_t datalen)
101 ssize_t filesize;
102 int fd = open(filename.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
104 if (fd < 0) {
105 Log::error("open(%s) failed: %s", filename.c_str(), strerror(errno));
106 return false;
109 filesize = write(fd, data, datalen);
110 if (fd < 0)
111 Log::error("write(%s) failed: %s", filename.c_str(), strerror(errno));
113 close(fd);
114 if (filesize == (ssize_t) datalen)
115 return true;
117 remove(filename.c_str());
118 return false;
121 bool File::exists(std::string filename)
123 struct stat buf;
125 return stat(filename.c_str(), &buf) >= 0;