blob: 626c37dae9426c82c3d66f286a374e982a80eced [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
Chaoren Lind3173f32015-05-29 19:52:29 +000038FileSystem::MakeDirectory(const FileSpec &file_spec, uint32_t file_permissions)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000039{
Chaoren Lind3173f32015-05-29 19:52:29 +000040 if (file_spec)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000041 {
Chaoren Lind3173f32015-05-29 19:52:29 +000042 Error error;
43 if (::mkdir(file_spec.GetCString(), file_permissions) == -1)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000044 {
45 error.SetErrorToErrno();
Chaoren Lind3173f32015-05-29 19:52:29 +000046 errno = 0;
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000047 switch (error.GetError())
48 {
49 case ENOENT:
50 {
51 // Parent directory doesn't exist, so lets make it if we can
Chaoren Lind3173f32015-05-29 19:52:29 +000052 // Make the parent directory and try again
53 FileSpec parent_file_spec{file_spec.GetDirectory().GetCString(), false};
54 error = MakeDirectory(parent_file_spec, file_permissions);
55 if (error.Fail())
56 return error;
57 // Try and make the directory again now that the parent directory was made successfully
58 if (::mkdir(file_spec.GetCString(), file_permissions) == -1)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000059 {
Chaoren Lind3173f32015-05-29 19:52:29 +000060 error.SetErrorToErrno();
61 return error;
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000062 }
63 }
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000064 case EEXIST:
65 {
Chaoren Lind3173f32015-05-29 19:52:29 +000066 if (file_spec.IsDirectory())
67 return Error{}; // It is a directory and it already exists
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000068 }
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000069 }
70 }
Chaoren Lind3173f32015-05-29 19:52:29 +000071 return error;
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000072 }
Chaoren Lind3173f32015-05-29 19:52:29 +000073 return Error{"empty path"};
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000074}
75
76Error
Chaoren Lind3173f32015-05-29 19:52:29 +000077FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000078{
79 Error error;
Chaoren Lind3173f32015-05-29 19:52:29 +000080 if (file_spec)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000081 {
82 if (recurse)
83 {
84 StreamString command;
Chaoren Lind3173f32015-05-29 19:52:29 +000085 command.Printf("rm -rf \"%s\"", file_spec.GetCString());
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000086 int status = ::system(command.GetString().c_str());
87 if (status != 0)
88 error.SetError(status, eErrorTypeGeneric);
89 }
90 else
91 {
Chaoren Lind3173f32015-05-29 19:52:29 +000092 if (::rmdir(file_spec.GetCString()) != 0)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000093 error.SetErrorToErrno();
94 }
95 }
96 else
97 {
98 error.SetErrorString("empty path");
99 }
100 return error;
101}
102
103Error
Chaoren Lind3173f32015-05-29 19:52:29 +0000104FileSystem::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000105{
106 Error error;
107 struct stat file_stats;
Chaoren Lind3173f32015-05-29 19:52:29 +0000108 if (::stat(file_spec.GetCString(), &file_stats) == 0)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000109 {
110 // The bits in "st_mode" currently match the definitions
111 // for the file mode bits in unix.
112 file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
113 }
114 else
115 {
116 error.SetErrorToErrno();
117 }
118 return error;
119}
120
121Error
Chaoren Lind3173f32015-05-29 19:52:29 +0000122FileSystem::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000123{
124 Error error;
Chaoren Lind3173f32015-05-29 19:52:29 +0000125 if (::chmod(file_spec.GetCString(), file_permissions) != 0)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000126 error.SetErrorToErrno();
127 return error;
128}
129
130lldb::user_id_t
131FileSystem::GetFileSize(const FileSpec &file_spec)
132{
133 return file_spec.GetByteSize();
134}
135
136bool
137FileSystem::GetFileExists(const FileSpec &file_spec)
138{
139 return file_spec.Exists();
140}
141
142Error
Chaoren Lind3173f32015-05-29 19:52:29 +0000143FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst)
Oleksiy Vyalova9ea0712015-05-08 23:54:34 +0000144{
145 Error error;
Chaoren Lind3173f32015-05-29 19:52:29 +0000146 if (::link(dst.GetCString(), src.GetCString()) == -1)
Oleksiy Vyalova9ea0712015-05-08 23:54:34 +0000147 error.SetErrorToErrno();
148 return error;
149}
150
151Error
Chaoren Lind3173f32015-05-29 19:52:29 +0000152FileSystem::Symlink(const FileSpec &src, const FileSpec &dst)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000153{
154 Error error;
Chaoren Lind3173f32015-05-29 19:52:29 +0000155 if (::symlink(dst.GetCString(), src.GetCString()) == -1)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000156 error.SetErrorToErrno();
157 return error;
158}
159
160Error
Chaoren Lind3173f32015-05-29 19:52:29 +0000161FileSystem::Unlink(const FileSpec &file_spec)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000162{
163 Error error;
Chaoren Lind3173f32015-05-29 19:52:29 +0000164 if (::unlink(file_spec.GetCString()) == -1)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000165 error.SetErrorToErrno();
166 return error;
167}
168
169Error
Chaoren Lind3173f32015-05-29 19:52:29 +0000170FileSystem::Readlink(const FileSpec &src, FileSpec &dst)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000171{
172 Error error;
Chaoren Lind3173f32015-05-29 19:52:29 +0000173 char buf[PATH_MAX];
174 ssize_t count = ::readlink(src.GetCString(), buf, sizeof(buf) - 1);
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000175 if (count < 0)
176 error.SetErrorToErrno();
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000177 else
Chaoren Lind3173f32015-05-29 19:52:29 +0000178 {
179 buf[count] = '\0'; // Success
180 dst.SetFile(buf, false);
181 }
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000182 return error;
183}
Greg Clayton736888c2015-02-23 23:47:09 +0000184
Vince Harron294aeb92015-02-24 05:14:49 +0000185static bool IsLocal(const struct statfs& info)
186{
187#ifdef __linux__
188 #define CIFS_MAGIC_NUMBER 0xFF534D42
Omair Javaida77ca512015-04-27 12:01:59 +0000189 switch ((uint32_t)info.f_type)
Vince Harron294aeb92015-02-24 05:14:49 +0000190 {
191 case NFS_SUPER_MAGIC:
192 case SMB_SUPER_MAGIC:
193 case CIFS_MAGIC_NUMBER:
194 return false;
195 default:
196 return true;
197 }
198#else
199 return (info.f_flags & MNT_LOCAL) != 0;
200#endif
201}
202
Greg Clayton736888c2015-02-23 23:47:09 +0000203bool
204FileSystem::IsLocal(const FileSpec &spec)
205{
206 struct statfs statfs_info;
207 std::string path (spec.GetPath());
Vince Harronf7839222015-02-24 05:24:12 +0000208 if (statfs(path.c_str(), &statfs_info) == 0)
Vince Harron294aeb92015-02-24 05:14:49 +0000209 return ::IsLocal(statfs_info);
Greg Clayton736888c2015-02-23 23:47:09 +0000210 return false;
211}