]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Host/posix/FileSystem.cpp
Merge ^/head r274961 through r275386.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Host / posix / FileSystem.cpp
1 //===-- FileSystem.cpp ------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Host/FileSystem.h"
11
12 // C includes
13 #include <sys/stat.h>
14 #include <sys/types.h>
15
16 // lldb Includes
17 #include "lldb/Core/Error.h"
18 #include "lldb/Core/StreamString.h"
19 #include "lldb/Host/Host.h"
20
21 using namespace lldb;
22 using namespace lldb_private;
23
24 FileSpec::PathSyntax
25 FileSystem::GetNativePathSyntax()
26 {
27     return FileSpec::ePathSyntaxPosix;
28 }
29
30 Error
31 FileSystem::MakeDirectory(const char *path, uint32_t file_permissions)
32 {
33     Error error;
34     if (path && path[0])
35     {
36         if (::mkdir(path, file_permissions) != 0)
37         {
38             error.SetErrorToErrno();
39             switch (error.GetError())
40             {
41                 case ENOENT:
42                 {
43                     // Parent directory doesn't exist, so lets make it if we can
44                     FileSpec spec(path, false);
45                     if (spec.GetDirectory() && spec.GetFilename())
46                     {
47                         // Make the parent directory and try again
48                         Error error2 = MakeDirectory(spec.GetDirectory().GetCString(), file_permissions);
49                         if (error2.Success())
50                         {
51                             // Try and make the directory again now that the parent directory was made successfully
52                             if (::mkdir(path, file_permissions) == 0)
53                                 error.Clear();
54                             else
55                                 error.SetErrorToErrno();
56                         }
57                     }
58                 }
59                 break;
60
61                 case EEXIST:
62                 {
63                     FileSpec path_spec(path, false);
64                     if (path_spec.IsDirectory())
65                         error.Clear(); // It is a directory and it already exists
66                 }
67                 break;
68             }
69         }
70     }
71     else
72     {
73         error.SetErrorString("empty path");
74     }
75     return error;
76 }
77
78 Error
79 FileSystem::DeleteDirectory(const char *path, bool recurse)
80 {
81     Error error;
82     if (path && path[0])
83     {
84         if (recurse)
85         {
86             StreamString command;
87             command.Printf("rm -rf \"%s\"", path);
88             int status = ::system(command.GetString().c_str());
89             if (status != 0)
90                 error.SetError(status, eErrorTypeGeneric);
91         }
92         else
93         {
94             if (::rmdir(path) != 0)
95                 error.SetErrorToErrno();
96         }
97     }
98     else
99     {
100         error.SetErrorString("empty path");
101     }
102     return error;
103 }
104
105 Error
106 FileSystem::GetFilePermissions(const char *path, uint32_t &file_permissions)
107 {
108     Error error;
109     struct stat file_stats;
110     if (::stat(path, &file_stats) == 0)
111     {
112         // The bits in "st_mode" currently match the definitions
113         // for the file mode bits in unix.
114         file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
115     }
116     else
117     {
118         error.SetErrorToErrno();
119     }
120     return error;
121 }
122
123 Error
124 FileSystem::SetFilePermissions(const char *path, uint32_t file_permissions)
125 {
126     Error error;
127     if (::chmod(path, file_permissions) != 0)
128         error.SetErrorToErrno();
129     return error;
130 }
131
132 lldb::user_id_t
133 FileSystem::GetFileSize(const FileSpec &file_spec)
134 {
135     return file_spec.GetByteSize();
136 }
137
138 bool
139 FileSystem::GetFileExists(const FileSpec &file_spec)
140 {
141     return file_spec.Exists();
142 }
143
144 Error
145 FileSystem::Symlink(const char *src, const char *dst)
146 {
147     Error error;
148     if (::symlink(dst, src) == -1)
149         error.SetErrorToErrno();
150     return error;
151 }
152
153 Error
154 FileSystem::Unlink(const char *path)
155 {
156     Error error;
157     if (::unlink(path) == -1)
158         error.SetErrorToErrno();
159     return error;
160 }
161
162 Error
163 FileSystem::Readlink(const char *path, char *buf, size_t buf_len)
164 {
165     Error error;
166     ssize_t count = ::readlink(path, buf, buf_len);
167     if (count < 0)
168         error.SetErrorToErrno();
169     else if (static_cast<size_t>(count) < (buf_len - 1))
170         buf[count] = '\0'; // Success
171     else
172         error.SetErrorString("'buf' buffer is too small to contain link contents");
173     return error;
174 }
175
176 bool
177 FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high)
178 {
179 #if defined(__APPLE__)
180     StreamString md5_cmd_line;
181     md5_cmd_line.Printf("md5 -q '%s'", file_spec.GetPath().c_str());
182     std::string hash_string;
183     Error err = Host::RunShellCommand(md5_cmd_line.GetData(), NULL, NULL, NULL, &hash_string, 60);
184     if (err.Fail())
185         return false;
186     // a correctly formed MD5 is 16-bytes, that is 32 hex digits
187     // if the output is any other length it is probably wrong
188     if (hash_string.size() != 32)
189         return false;
190     std::string part1(hash_string, 0, 16);
191     std::string part2(hash_string, 16);
192     const char *part1_cstr = part1.c_str();
193     const char *part2_cstr = part2.c_str();
194     high = ::strtoull(part1_cstr, NULL, 16);
195     low = ::strtoull(part2_cstr, NULL, 16);
196     return true;
197 #else
198     // your own MD5 implementation here
199     return false;
200 #endif
201 }