blob: 15ded773408dda3327b134980fa219191d8d62ce [file] [log] [blame]
Zachary Turnerc00cf4a2014-08-15 22:04:21 +00001//===-- 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
Greg Clayton736888c2015-02-23 23:47:09 +000013#include <sys/mount.h>
14#include <sys/param.h>
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000015#include <sys/stat.h>
16#include <sys/types.h>
Vince Harron294aeb92015-02-24 05:14:49 +000017#ifdef __linux__
18#include <sys/statfs.h>
19#include <sys/mount.h>
20#include <linux/magic.h>
21#endif
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000022
23// lldb Includes
24#include "lldb/Core/Error.h"
25#include "lldb/Core/StreamString.h"
26#include "lldb/Host/Host.h"
27
28using namespace lldb;
29using namespace lldb_private;
30
31FileSpec::PathSyntax
32FileSystem::GetNativePathSyntax()
33{
34 return FileSpec::ePathSyntaxPosix;
35}
36
37Error
38FileSystem::MakeDirectory(const char *path, uint32_t file_permissions)
39{
40 Error error;
41 if (path && path[0])
42 {
43 if (::mkdir(path, file_permissions) != 0)
44 {
45 error.SetErrorToErrno();
46 switch (error.GetError())
47 {
48 case ENOENT:
49 {
50 // Parent directory doesn't exist, so lets make it if we can
51 FileSpec spec(path, false);
52 if (spec.GetDirectory() && spec.GetFilename())
53 {
54 // Make the parent directory and try again
55 Error error2 = MakeDirectory(spec.GetDirectory().GetCString(), file_permissions);
56 if (error2.Success())
57 {
58 // Try and make the directory again now that the parent directory was made successfully
59 if (::mkdir(path, file_permissions) == 0)
60 error.Clear();
61 else
62 error.SetErrorToErrno();
63 }
64 }
65 }
66 break;
67
68 case EEXIST:
69 {
70 FileSpec path_spec(path, false);
71 if (path_spec.IsDirectory())
72 error.Clear(); // It is a directory and it already exists
73 }
74 break;
75 }
76 }
77 }
78 else
79 {
80 error.SetErrorString("empty path");
81 }
82 return error;
83}
84
85Error
86FileSystem::DeleteDirectory(const char *path, bool recurse)
87{
88 Error error;
89 if (path && path[0])
90 {
91 if (recurse)
92 {
93 StreamString command;
94 command.Printf("rm -rf \"%s\"", path);
95 int status = ::system(command.GetString().c_str());
96 if (status != 0)
97 error.SetError(status, eErrorTypeGeneric);
98 }
99 else
100 {
101 if (::rmdir(path) != 0)
102 error.SetErrorToErrno();
103 }
104 }
105 else
106 {
107 error.SetErrorString("empty path");
108 }
109 return error;
110}
111
112Error
113FileSystem::GetFilePermissions(const char *path, uint32_t &file_permissions)
114{
115 Error error;
116 struct stat file_stats;
117 if (::stat(path, &file_stats) == 0)
118 {
119 // The bits in "st_mode" currently match the definitions
120 // for the file mode bits in unix.
121 file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
122 }
123 else
124 {
125 error.SetErrorToErrno();
126 }
127 return error;
128}
129
130Error
131FileSystem::SetFilePermissions(const char *path, uint32_t file_permissions)
132{
133 Error error;
134 if (::chmod(path, file_permissions) != 0)
135 error.SetErrorToErrno();
136 return error;
137}
138
139lldb::user_id_t
140FileSystem::GetFileSize(const FileSpec &file_spec)
141{
142 return file_spec.GetByteSize();
143}
144
145bool
146FileSystem::GetFileExists(const FileSpec &file_spec)
147{
148 return file_spec.Exists();
149}
150
151Error
Oleksiy Vyalova9ea0712015-05-08 23:54:34 +0000152FileSystem::Hardlink(const char *src, const char *dst)
153{
154 Error error;
155 if (::link(dst, src) == -1)
156 error.SetErrorToErrno();
157 return error;
158}
159
160Error
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000161FileSystem::Symlink(const char *src, const char *dst)
162{
163 Error error;
164 if (::symlink(dst, src) == -1)
165 error.SetErrorToErrno();
166 return error;
167}
168
169Error
170FileSystem::Unlink(const char *path)
171{
172 Error error;
173 if (::unlink(path) == -1)
174 error.SetErrorToErrno();
175 return error;
176}
177
178Error
179FileSystem::Readlink(const char *path, char *buf, size_t buf_len)
180{
181 Error error;
182 ssize_t count = ::readlink(path, buf, buf_len);
183 if (count < 0)
184 error.SetErrorToErrno();
185 else if (static_cast<size_t>(count) < (buf_len - 1))
186 buf[count] = '\0'; // Success
187 else
188 error.SetErrorString("'buf' buffer is too small to contain link contents");
189 return error;
190}
Greg Clayton736888c2015-02-23 23:47:09 +0000191
Vince Harron294aeb92015-02-24 05:14:49 +0000192static bool IsLocal(const struct statfs& info)
193{
194#ifdef __linux__
195 #define CIFS_MAGIC_NUMBER 0xFF534D42
Omair Javaida77ca512015-04-27 12:01:59 +0000196 switch ((uint32_t)info.f_type)
Vince Harron294aeb92015-02-24 05:14:49 +0000197 {
198 case NFS_SUPER_MAGIC:
199 case SMB_SUPER_MAGIC:
200 case CIFS_MAGIC_NUMBER:
201 return false;
202 default:
203 return true;
204 }
205#else
206 return (info.f_flags & MNT_LOCAL) != 0;
207#endif
208}
209
Greg Clayton736888c2015-02-23 23:47:09 +0000210bool
211FileSystem::IsLocal(const FileSpec &spec)
212{
213 struct statfs statfs_info;
214 std::string path (spec.GetPath());
Vince Harronf7839222015-02-24 05:24:12 +0000215 if (statfs(path.c_str(), &statfs_info) == 0)
Vince Harron294aeb92015-02-24 05:14:49 +0000216 return ::IsLocal(statfs_info);
Greg Clayton736888c2015-02-23 23:47:09 +0000217 return false;
218}