Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "services/files/directory_impl.h" |
| 6 | |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 7 | #include <dirent.h> |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 8 | #include <errno.h> |
| 9 | #include <fcntl.h> |
| 10 | #include <stdio.h> |
| 11 | #include <sys/stat.h> |
| 12 | #include <sys/types.h> |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 13 | #include <unistd.h> |
| 14 | |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 15 | #include "base/files/scoped_temp_dir.h" |
| 16 | #include "base/logging.h" |
| 17 | #include "base/memory/scoped_ptr.h" |
| 18 | #include "base/posix/eintr_wrapper.h" |
| 19 | #include "build/build_config.h" |
| 20 | #include "services/files/file_impl.h" |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 21 | #include "services/files/shared_impl.h" |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 22 | #include "services/files/util.h" |
| 23 | |
| 24 | namespace mojo { |
| 25 | namespace files { |
| 26 | |
| 27 | namespace { |
| 28 | |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 29 | // Calls |closedir()| on a |DIR*|. |
| 30 | struct DIRDeleter { |
| 31 | void operator()(DIR* dir) const { PCHECK(closedir(dir) == 0); } |
| 32 | }; |
Viet-Trung Luu | 06acf5f | 2015-03-13 11:05:31 -0700 | [diff] [blame] | 33 | using ScopedDIR = scoped_ptr<DIR, DIRDeleter>; |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 34 | |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 35 | Error ValidateOpenFlags(uint32_t open_flags, bool is_directory) { |
| 36 | // Treat unknown flags as "unimplemented". |
| 37 | if ((open_flags & |
| 38 | ~(kOpenFlagRead | kOpenFlagWrite | kOpenFlagCreate | kOpenFlagExclusive | |
| 39 | kOpenFlagAppend | kOpenFlagTruncate))) |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 40 | return Error::UNIMPLEMENTED; |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 41 | |
| 42 | // At least one of |kOpenFlagRead| or |kOpenFlagWrite| must be set. |
| 43 | if (!(open_flags & (kOpenFlagRead | kOpenFlagWrite))) |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 44 | return Error::INVALID_ARGUMENT; |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 45 | |
| 46 | // |kOpenFlagCreate| requires |kOpenFlagWrite|. |
| 47 | if ((open_flags & kOpenFlagCreate) && !(open_flags & kOpenFlagWrite)) |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 48 | return Error::INVALID_ARGUMENT; |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 49 | |
| 50 | // |kOpenFlagExclusive| requires |kOpenFlagCreate|. |
| 51 | if ((open_flags & kOpenFlagExclusive) && !(open_flags & kOpenFlagCreate)) |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 52 | return Error::INVALID_ARGUMENT; |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 53 | |
| 54 | if (is_directory) { |
| 55 | // Check that file-only flags aren't set. |
| 56 | if ((open_flags & (kOpenFlagAppend | kOpenFlagTruncate))) |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 57 | return Error::INVALID_ARGUMENT; |
| 58 | return Error::OK; |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | // File-only flags: |
| 62 | |
| 63 | // |kOpenFlagAppend| requires |kOpenFlagWrite|. |
| 64 | if ((open_flags & kOpenFlagAppend) && !(open_flags & kOpenFlagWrite)) |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 65 | return Error::INVALID_ARGUMENT; |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 66 | |
| 67 | // |kOpenFlagTruncate| requires |kOpenFlagWrite|. |
| 68 | if ((open_flags & kOpenFlagTruncate) && !(open_flags & kOpenFlagWrite)) |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 69 | return Error::INVALID_ARGUMENT; |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 70 | |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 71 | return Error::OK; |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 72 | } |
| 73 | |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 74 | Error ValidateDeleteFlags(uint32_t delete_flags) { |
| 75 | // Treat unknown flags as "unimplemented". |
| 76 | if ((delete_flags & |
| 77 | ~(kDeleteFlagFileOnly | kDeleteFlagDirectoryOnly | |
| 78 | kDeleteFlagRecursive))) |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 79 | return Error::UNIMPLEMENTED; |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 80 | |
| 81 | // Only one of the three currently-defined flags may be set. |
| 82 | if ((delete_flags & kDeleteFlagFileOnly) && |
| 83 | (delete_flags & (kDeleteFlagDirectoryOnly | kDeleteFlagRecursive))) |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 84 | return Error::INVALID_ARGUMENT; |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 85 | if ((delete_flags & kDeleteFlagDirectoryOnly) && |
| 86 | (delete_flags & (kDeleteFlagFileOnly | kDeleteFlagRecursive))) |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 87 | return Error::INVALID_ARGUMENT; |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 88 | if ((delete_flags & kDeleteFlagRecursive) && |
| 89 | (delete_flags & (kDeleteFlagFileOnly | kDeleteFlagDirectoryOnly))) |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 90 | return Error::INVALID_ARGUMENT; |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 91 | |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 92 | return Error::OK; |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 93 | } |
| 94 | |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 95 | } // namespace |
| 96 | |
| 97 | DirectoryImpl::DirectoryImpl(InterfaceRequest<Directory> request, |
| 98 | base::ScopedFD dir_fd, |
| 99 | scoped_ptr<base::ScopedTempDir> temp_dir) |
| 100 | : binding_(this, request.Pass()), |
| 101 | dir_fd_(dir_fd.Pass()), |
| 102 | temp_dir_(temp_dir.Pass()) { |
| 103 | DCHECK(dir_fd_.is_valid()); |
| 104 | } |
| 105 | |
| 106 | DirectoryImpl::~DirectoryImpl() { |
| 107 | } |
| 108 | |
Viet-Trung Luu | 0580624 | 2015-04-03 10:17:37 -0700 | [diff] [blame] | 109 | void DirectoryImpl::Read(const ReadCallback& callback) { |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 110 | static const size_t kMaxReadCount = 1000; |
| 111 | |
| 112 | DCHECK(dir_fd_.is_valid()); |
| 113 | |
| 114 | // |fdopendir()| takes ownership of the FD (giving it to the |DIR| -- |
| 115 | // |closedir()| will close the FD)), so we need to |dup()| ours. |
| 116 | base::ScopedFD fd(dup(dir_fd_.get())); |
| 117 | if (!fd.is_valid()) { |
Viet-Trung Luu | 06341ac | 2015-11-19 13:02:01 -0800 | [diff] [blame] | 118 | callback.Run(ErrnoToError(errno), nullptr); |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 119 | return; |
| 120 | } |
| 121 | |
| 122 | ScopedDIR dir(fdopendir(fd.release())); |
| 123 | if (!dir) { |
Viet-Trung Luu | 06341ac | 2015-11-19 13:02:01 -0800 | [diff] [blame] | 124 | callback.Run(ErrnoToError(errno), nullptr); |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 125 | return; |
| 126 | } |
| 127 | |
James Robinson | dc335c0 | 2015-10-09 17:23:30 -0700 | [diff] [blame] | 128 | auto result = Array<DirectoryEntryPtr>::New(0); |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 129 | |
| 130 | // Warning: This is not portable (per POSIX.1 -- |buffer| may not be large |
| 131 | // enough), but it's fine for Linux. |
| 132 | #if !defined(OS_ANDROID) && !defined(OS_LINUX) |
| 133 | #error "Use of struct dirent for readdir_r() buffer not portable; please check." |
| 134 | #endif |
| 135 | struct dirent buffer; |
| 136 | for (size_t n = 0;;) { |
| 137 | struct dirent* entry = nullptr; |
| 138 | if (int error = readdir_r(dir.get(), &buffer, &entry)) { |
| 139 | // |error| is effectively an errno (for |readdir_r()|), AFAICT. |
Viet-Trung Luu | 06341ac | 2015-11-19 13:02:01 -0800 | [diff] [blame] | 140 | callback.Run(ErrnoToError(error), nullptr); |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 141 | return; |
| 142 | } |
| 143 | |
| 144 | if (!entry) |
| 145 | break; |
| 146 | |
| 147 | n++; |
| 148 | if (n > kMaxReadCount) { |
| 149 | LOG(WARNING) << "Directory contents truncated"; |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 150 | callback.Run(Error::OUT_OF_RANGE, result.Pass()); |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 151 | return; |
| 152 | } |
| 153 | |
| 154 | DirectoryEntryPtr e = DirectoryEntry::New(); |
| 155 | switch (entry->d_type) { |
| 156 | case DT_DIR: |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 157 | e->type = FileType::DIRECTORY; |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 158 | break; |
| 159 | case DT_REG: |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 160 | e->type = FileType::REGULAR_FILE; |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 161 | break; |
| 162 | default: |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 163 | e->type = FileType::UNKNOWN; |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 164 | break; |
| 165 | } |
| 166 | e->name = String(entry->d_name); |
| 167 | result.push_back(e.Pass()); |
| 168 | } |
| 169 | |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 170 | callback.Run(Error::OK, result.Pass()); |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 171 | } |
| 172 | |
Viet-Trung Luu | 0580624 | 2015-04-03 10:17:37 -0700 | [diff] [blame] | 173 | void DirectoryImpl::Stat(const StatCallback& callback) { |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 174 | DCHECK(dir_fd_.is_valid()); |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 175 | StatFD(dir_fd_.get(), FileType::DIRECTORY, callback); |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 176 | } |
| 177 | |
| 178 | void DirectoryImpl::Touch(TimespecOrNowPtr atime, |
| 179 | TimespecOrNowPtr mtime, |
Viet-Trung Luu | 0580624 | 2015-04-03 10:17:37 -0700 | [diff] [blame] | 180 | const TouchCallback& callback) { |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 181 | DCHECK(dir_fd_.is_valid()); |
| 182 | TouchFD(dir_fd_.get(), atime.Pass(), mtime.Pass(), callback); |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 183 | } |
| 184 | |
| 185 | // TODO(vtl): Move the implementation to a thread pool. |
| 186 | void DirectoryImpl::OpenFile(const String& path, |
| 187 | InterfaceRequest<File> file, |
| 188 | uint32_t open_flags, |
Viet-Trung Luu | 0580624 | 2015-04-03 10:17:37 -0700 | [diff] [blame] | 189 | const OpenFileCallback& callback) { |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 190 | DCHECK(!path.is_null()); |
| 191 | DCHECK(dir_fd_.is_valid()); |
| 192 | |
John Grossman | 08f574e | 2015-09-22 16:57:57 -0700 | [diff] [blame] | 193 | Error error = IsPathValid(path); |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 194 | if (error != Error::OK) { |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 195 | callback.Run(error); |
| 196 | return; |
| 197 | } |
| 198 | // TODO(vtl): Make sure the path doesn't exit this directory (if appropriate). |
| 199 | // TODO(vtl): Maybe allow absolute paths? |
| 200 | |
John Grossman | 08f574e | 2015-09-22 16:57:57 -0700 | [diff] [blame] | 201 | error = ValidateOpenFlags(open_flags, false); |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 202 | if (error != Error::OK) { |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 203 | callback.Run(error); |
| 204 | return; |
| 205 | } |
| 206 | |
| 207 | int flags = 0; |
| 208 | if ((open_flags & kOpenFlagRead)) |
| 209 | flags |= (open_flags & kOpenFlagWrite) ? O_RDWR : O_RDONLY; |
| 210 | else |
| 211 | flags |= O_WRONLY; |
| 212 | if ((open_flags & kOpenFlagCreate)) |
| 213 | flags |= O_CREAT; |
| 214 | if ((open_flags & kOpenFlagExclusive)) |
| 215 | flags |= O_EXCL; |
| 216 | if ((open_flags & kOpenFlagAppend)) |
| 217 | flags |= O_APPEND; |
| 218 | if ((open_flags & kOpenFlagTruncate)) |
| 219 | flags |= O_TRUNC; |
| 220 | |
| 221 | base::ScopedFD file_fd( |
| 222 | HANDLE_EINTR(openat(dir_fd_.get(), path.get().c_str(), flags, 0600))); |
| 223 | if (!file_fd.is_valid()) { |
| 224 | callback.Run(ErrnoToError(errno)); |
| 225 | return; |
| 226 | } |
| 227 | |
| 228 | if (file.is_pending()) |
| 229 | new FileImpl(file.Pass(), file_fd.Pass()); |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 230 | callback.Run(Error::OK); |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | void DirectoryImpl::OpenDirectory(const String& path, |
| 234 | InterfaceRequest<Directory> directory, |
| 235 | uint32_t open_flags, |
Viet-Trung Luu | 0580624 | 2015-04-03 10:17:37 -0700 | [diff] [blame] | 236 | const OpenDirectoryCallback& callback) { |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 237 | DCHECK(!path.is_null()); |
| 238 | DCHECK(dir_fd_.is_valid()); |
| 239 | |
John Grossman | 08f574e | 2015-09-22 16:57:57 -0700 | [diff] [blame] | 240 | Error error = IsPathValid(path); |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 241 | if (error != Error::OK) { |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 242 | callback.Run(error); |
| 243 | return; |
| 244 | } |
| 245 | // TODO(vtl): Make sure the path doesn't exit this directory (if appropriate). |
| 246 | // TODO(vtl): Maybe allow absolute paths? |
| 247 | |
John Grossman | 08f574e | 2015-09-22 16:57:57 -0700 | [diff] [blame] | 248 | error = ValidateOpenFlags(open_flags, false); |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 249 | if (error != Error::OK) { |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 250 | callback.Run(error); |
| 251 | return; |
| 252 | } |
| 253 | |
| 254 | // TODO(vtl): Implement read-only (whatever that means). |
| 255 | if (!(open_flags & kOpenFlagWrite)) { |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 256 | callback.Run(Error::UNIMPLEMENTED); |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 257 | return; |
| 258 | } |
| 259 | |
| 260 | if ((open_flags & kOpenFlagCreate)) { |
| 261 | if (mkdirat(dir_fd_.get(), path.get().c_str(), 0700) != 0) { |
| 262 | // Allow |EEXIST| if |kOpenFlagExclusive| is not set. Note, however, that |
| 263 | // it does not guarantee that |path| is a directory. |
| 264 | // TODO(vtl): Hrm, ponder if we should check that |path| is a directory. |
John McCutchan | 2c2b5c8 | 2015-12-18 15:13:45 -0800 | [diff] [blame] | 265 | if ((errno != EEXIST) || (open_flags & kOpenFlagExclusive)) { |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 266 | callback.Run(ErrnoToError(errno)); |
| 267 | return; |
| 268 | } |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | base::ScopedFD new_dir_fd( |
| 273 | HANDLE_EINTR(openat(dir_fd_.get(), path.get().c_str(), O_DIRECTORY, 0))); |
| 274 | if (!new_dir_fd.is_valid()) { |
| 275 | callback.Run(ErrnoToError(errno)); |
| 276 | return; |
| 277 | } |
| 278 | |
| 279 | if (directory.is_pending()) |
| 280 | new DirectoryImpl(directory.Pass(), new_dir_fd.Pass(), nullptr); |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 281 | callback.Run(Error::OK); |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 282 | } |
| 283 | |
| 284 | void DirectoryImpl::Rename(const String& path, |
| 285 | const String& new_path, |
Viet-Trung Luu | 0580624 | 2015-04-03 10:17:37 -0700 | [diff] [blame] | 286 | const RenameCallback& callback) { |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 287 | DCHECK(!path.is_null()); |
| 288 | DCHECK(!new_path.is_null()); |
| 289 | DCHECK(dir_fd_.is_valid()); |
| 290 | |
John Grossman | 08f574e | 2015-09-22 16:57:57 -0700 | [diff] [blame] | 291 | Error error = IsPathValid(path); |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 292 | if (error != Error::OK) { |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 293 | callback.Run(error); |
| 294 | return; |
| 295 | } |
John Grossman | 08f574e | 2015-09-22 16:57:57 -0700 | [diff] [blame] | 296 | |
| 297 | error = IsPathValid(new_path); |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 298 | if (error != Error::OK) { |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 299 | callback.Run(error); |
| 300 | return; |
| 301 | } |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 302 | // TODO(vtl): See TODOs about |path| in OpenFile(). |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 303 | |
| 304 | if (renameat(dir_fd_.get(), path.get().c_str(), dir_fd_.get(), |
| 305 | new_path.get().c_str())) { |
| 306 | callback.Run(ErrnoToError(errno)); |
| 307 | return; |
| 308 | } |
| 309 | |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 310 | callback.Run(Error::OK); |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 311 | } |
| 312 | |
| 313 | void DirectoryImpl::Delete(const String& path, |
| 314 | uint32_t delete_flags, |
Viet-Trung Luu | 0580624 | 2015-04-03 10:17:37 -0700 | [diff] [blame] | 315 | const DeleteCallback& callback) { |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 316 | DCHECK(!path.is_null()); |
| 317 | DCHECK(dir_fd_.is_valid()); |
| 318 | |
John Grossman | 08f574e | 2015-09-22 16:57:57 -0700 | [diff] [blame] | 319 | Error error = IsPathValid(path); |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 320 | if (error != Error::OK) { |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 321 | callback.Run(error); |
| 322 | return; |
| 323 | } |
| 324 | // TODO(vtl): See TODOs about |path| in OpenFile(). |
| 325 | |
John Grossman | 08f574e | 2015-09-22 16:57:57 -0700 | [diff] [blame] | 326 | error = ValidateDeleteFlags(delete_flags); |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 327 | if (error != Error::OK) { |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 328 | callback.Run(error); |
| 329 | return; |
| 330 | } |
| 331 | |
| 332 | // TODO(vtl): Recursive not yet supported. |
| 333 | if ((delete_flags & kDeleteFlagRecursive)) { |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 334 | callback.Run(Error::UNIMPLEMENTED); |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 335 | return; |
| 336 | } |
| 337 | |
| 338 | // First try deleting it as a file, unless we're told to do directory-only. |
| 339 | if (!(delete_flags & kDeleteFlagDirectoryOnly)) { |
| 340 | if (unlinkat(dir_fd_.get(), path.get().c_str(), 0) == 0) { |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 341 | callback.Run(Error::OK); |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 342 | return; |
| 343 | } |
| 344 | |
| 345 | // If file-only, don't continue. |
| 346 | if ((delete_flags & kDeleteFlagFileOnly)) { |
| 347 | callback.Run(ErrnoToError(errno)); |
| 348 | return; |
| 349 | } |
| 350 | } |
| 351 | |
| 352 | // Try deleting it as a directory. |
| 353 | if (unlinkat(dir_fd_.get(), path.get().c_str(), AT_REMOVEDIR) == 0) { |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 354 | callback.Run(Error::OK); |
Viet-Trung Luu | 451ed41 | 2015-03-09 11:11:11 -0700 | [diff] [blame] | 355 | return; |
| 356 | } |
| 357 | |
| 358 | callback.Run(ErrnoToError(errno)); |
Viet-Trung Luu | 2a39449 | 2015-03-04 08:03:20 -0800 | [diff] [blame] | 359 | } |
| 360 | |
| 361 | } // namespace files |
| 362 | } // namespace mojo |