blob: 1ec53e2cc6619e0b1a4412fe40f3c67eb0f2213a [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
Chaoren Lin226937e2015-06-27 23:11:34 +000013#include <dirent.h>
Greg Clayton736888c2015-02-23 23:47:09 +000014#include <sys/mount.h>
15#include <sys/param.h>
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000016#include <sys/stat.h>
17#include <sys/types.h>
Vince Harron294aeb92015-02-24 05:14:49 +000018#ifdef __linux__
19#include <sys/statfs.h>
20#include <sys/mount.h>
21#include <linux/magic.h>
22#endif
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000023
24// lldb Includes
25#include "lldb/Core/Error.h"
26#include "lldb/Core/StreamString.h"
27#include "lldb/Host/Host.h"
28
29using namespace lldb;
30using namespace lldb_private;
31
32FileSpec::PathSyntax
33FileSystem::GetNativePathSyntax()
34{
35 return FileSpec::ePathSyntaxPosix;
36}
37
38Error
Chaoren Lind3173f32015-05-29 19:52:29 +000039FileSystem::MakeDirectory(const FileSpec &file_spec, uint32_t file_permissions)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000040{
Chaoren Lind3173f32015-05-29 19:52:29 +000041 if (file_spec)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000042 {
Chaoren Lind3173f32015-05-29 19:52:29 +000043 Error error;
44 if (::mkdir(file_spec.GetCString(), file_permissions) == -1)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000045 {
46 error.SetErrorToErrno();
Chaoren Lind3173f32015-05-29 19:52:29 +000047 errno = 0;
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000048 switch (error.GetError())
49 {
50 case ENOENT:
51 {
52 // Parent directory doesn't exist, so lets make it if we can
Chaoren Lind3173f32015-05-29 19:52:29 +000053 // Make the parent directory and try again
54 FileSpec parent_file_spec{file_spec.GetDirectory().GetCString(), false};
55 error = MakeDirectory(parent_file_spec, file_permissions);
56 if (error.Fail())
57 return error;
58 // Try and make the directory again now that the parent directory was made successfully
59 if (::mkdir(file_spec.GetCString(), file_permissions) == -1)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000060 {
Chaoren Lind3173f32015-05-29 19:52:29 +000061 error.SetErrorToErrno();
62 return error;
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000063 }
64 }
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000065 case EEXIST:
66 {
Chaoren Lind3173f32015-05-29 19:52:29 +000067 if (file_spec.IsDirectory())
68 return Error{}; // It is a directory and it already exists
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000069 }
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000070 }
71 }
Chaoren Lind3173f32015-05-29 19:52:29 +000072 return error;
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000073 }
Chaoren Lind3173f32015-05-29 19:52:29 +000074 return Error{"empty path"};
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000075}
76
77Error
Chaoren Lind3173f32015-05-29 19:52:29 +000078FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000079{
80 Error error;
Chaoren Lind3173f32015-05-29 19:52:29 +000081 if (file_spec)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +000082 {
83 if (recurse)
84 {
Chaoren Lin226937e2015-06-27 23:11:34 +000085 DIR *dirp = opendir(file_spec.GetCString());
86 if (!dirp)
87 {
88 error.SetErrorToErrno();
89 return error;
90 }
91 struct dirent *direntp;
92 while (error.Success() && (direntp = readdir(dirp)))
93 {
94 if (direntp->d_type == DT_DIR)
95 error = DeleteDirectory(FileSpec{direntp->d_name, false}, true);
96 else if (::unlink(direntp->d_name) != 0)
97 error.SetErrorToErrno();
98 }
99 if (closedir(dirp) != 0)
100 error.SetErrorToErrno();
101 if (error.Fail())
102 return error;
103 return DeleteDirectory(file_spec, false);
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000104 }
105 else
106 {
Chaoren Lind3173f32015-05-29 19:52:29 +0000107 if (::rmdir(file_spec.GetCString()) != 0)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000108 error.SetErrorToErrno();
109 }
110 }
111 else
112 {
113 error.SetErrorString("empty path");
114 }
115 return error;
116}
117
118Error
Chaoren Lind3173f32015-05-29 19:52:29 +0000119FileSystem::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000120{
121 Error error;
122 struct stat file_stats;
Chaoren Lind3173f32015-05-29 19:52:29 +0000123 if (::stat(file_spec.GetCString(), &file_stats) == 0)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000124 {
125 // The bits in "st_mode" currently match the definitions
126 // for the file mode bits in unix.
127 file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
128 }
129 else
130 {
131 error.SetErrorToErrno();
132 }
133 return error;
134}
135
136Error
Chaoren Lind3173f32015-05-29 19:52:29 +0000137FileSystem::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000138{
139 Error error;
Chaoren Lind3173f32015-05-29 19:52:29 +0000140 if (::chmod(file_spec.GetCString(), file_permissions) != 0)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000141 error.SetErrorToErrno();
142 return error;
143}
144
145lldb::user_id_t
146FileSystem::GetFileSize(const FileSpec &file_spec)
147{
148 return file_spec.GetByteSize();
149}
150
151bool
152FileSystem::GetFileExists(const FileSpec &file_spec)
153{
154 return file_spec.Exists();
155}
156
157Error
Chaoren Lind3173f32015-05-29 19:52:29 +0000158FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst)
Oleksiy Vyalova9ea0712015-05-08 23:54:34 +0000159{
160 Error error;
Chaoren Lind3173f32015-05-29 19:52:29 +0000161 if (::link(dst.GetCString(), src.GetCString()) == -1)
Oleksiy Vyalova9ea0712015-05-08 23:54:34 +0000162 error.SetErrorToErrno();
163 return error;
164}
165
166Error
Chaoren Lind3173f32015-05-29 19:52:29 +0000167FileSystem::Symlink(const FileSpec &src, const FileSpec &dst)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000168{
169 Error error;
Chaoren Lind3173f32015-05-29 19:52:29 +0000170 if (::symlink(dst.GetCString(), src.GetCString()) == -1)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000171 error.SetErrorToErrno();
172 return error;
173}
174
175Error
Chaoren Lind3173f32015-05-29 19:52:29 +0000176FileSystem::Unlink(const FileSpec &file_spec)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000177{
178 Error error;
Chaoren Lind3173f32015-05-29 19:52:29 +0000179 if (::unlink(file_spec.GetCString()) == -1)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000180 error.SetErrorToErrno();
181 return error;
182}
183
184Error
Chaoren Lind3173f32015-05-29 19:52:29 +0000185FileSystem::Readlink(const FileSpec &src, FileSpec &dst)
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000186{
187 Error error;
Chaoren Lind3173f32015-05-29 19:52:29 +0000188 char buf[PATH_MAX];
189 ssize_t count = ::readlink(src.GetCString(), buf, sizeof(buf) - 1);
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000190 if (count < 0)
191 error.SetErrorToErrno();
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000192 else
Chaoren Lind3173f32015-05-29 19:52:29 +0000193 {
194 buf[count] = '\0'; // Success
195 dst.SetFile(buf, false);
196 }
Zachary Turnerc00cf4a2014-08-15 22:04:21 +0000197 return error;
198}
Greg Clayton736888c2015-02-23 23:47:09 +0000199
Vince Harron294aeb92015-02-24 05:14:49 +0000200static bool IsLocal(const struct statfs& info)
201{
202#ifdef __linux__
203 #define CIFS_MAGIC_NUMBER 0xFF534D42
Omair Javaida77ca512015-04-27 12:01:59 +0000204 switch ((uint32_t)info.f_type)
Vince Harron294aeb92015-02-24 05:14:49 +0000205 {
206 case NFS_SUPER_MAGIC:
207 case SMB_SUPER_MAGIC:
208 case CIFS_MAGIC_NUMBER:
209 return false;
210 default:
211 return true;
212 }
213#else
214 return (info.f_flags & MNT_LOCAL) != 0;
215#endif
216}
217
Greg Clayton736888c2015-02-23 23:47:09 +0000218bool
219FileSystem::IsLocal(const FileSpec &spec)
220{
221 struct statfs statfs_info;
222 std::string path (spec.GetPath());
Vince Harronf7839222015-02-24 05:24:12 +0000223 if (statfs(path.c_str(), &statfs_info) == 0)
Vince Harron294aeb92015-02-24 05:14:49 +0000224 return ::IsLocal(statfs_info);
Greg Clayton736888c2015-02-23 23:47:09 +0000225 return false;
226}