OLD | NEW |
---|---|
(Empty) | |
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 | |
7 #include <errno.h> | |
8 #include <fcntl.h> | |
9 #include <stdio.h> | |
10 #include <sys/stat.h> | |
11 #include <sys/types.h> | |
12 #include <time.h> | |
13 #include <unistd.h> | |
14 | |
15 #include "base/files/file_path.h" | |
16 #include "base/files/file_util.h" | |
17 #include "base/files/scoped_file.h" | |
18 #include "base/logging.h" | |
19 #include "base/memory/scoped_ptr.h" | |
20 #include "base/posix/eintr_wrapper.h" | |
21 #include "build/build_config.h" | |
22 #include "services/files/file_impl.h" | |
23 #include "services/files/util.h" | |
24 | |
25 namespace mojo { | |
26 namespace files { | |
27 | |
28 namespace { | |
29 | |
30 Error ValidateOpenFlags(uint32_t open_flags, bool is_directory) { | |
31 // Treat unknown flags as "unimplemented". | |
32 if ((open_flags & | |
33 ~(kOpenFlagRead | kOpenFlagWrite | kOpenFlagCreate | kOpenFlagExclusive | | |
34 kOpenFlagAppend | kOpenFlagTruncate))) | |
35 return ERROR_UNIMPLEMENTED; | |
36 | |
37 // At least one of |kOpenFlagRead| or |kOpenFlagWrite| must be set. | |
38 if (!(open_flags & (kOpenFlagRead | kOpenFlagWrite))) | |
39 return ERROR_INVALID_ARGUMENT; | |
40 | |
41 // |kOpenFlagCreate| requires |kOpenFlagWrite|. | |
42 if ((open_flags & kOpenFlagCreate) && !(open_flags & kOpenFlagWrite)) | |
43 return ERROR_INVALID_ARGUMENT; | |
44 | |
45 // |kOpenFlagExclusive| requires |kOpenFlagCreate|. | |
46 if ((open_flags & kOpenFlagExclusive) && !(open_flags & kOpenFlagCreate)) | |
47 return ERROR_INVALID_ARGUMENT; | |
48 | |
49 if (is_directory) { | |
50 // Check that file-only flags aren't set. | |
51 if ((open_flags & (kOpenFlagAppend | kOpenFlagTruncate))) | |
qsr
2015/03/03 11:56:44
You have one pair of parenthesis too many.
viettrungluu
2015/03/03 18:50:35
The extra pair of parentheses indicates that I rea
| |
52 return ERROR_INVALID_ARGUMENT; | |
53 return ERROR_OK; | |
54 } | |
55 | |
56 // File-only flags: | |
57 | |
58 // |kOpenFlagAppend| requires |kOpenFlagWrite|. | |
59 if ((open_flags & kOpenFlagAppend) && !(open_flags & kOpenFlagWrite)) | |
60 return ERROR_INVALID_ARGUMENT; | |
61 | |
62 // |kOpenFlagTruncate| requires |kOpenFlagWrite|. | |
63 if ((open_flags & kOpenFlagTruncate) && !(open_flags & kOpenFlagWrite)) | |
64 return ERROR_INVALID_ARGUMENT; | |
65 | |
66 return ERROR_OK; | |
67 } | |
68 | |
69 } // namespace | |
70 | |
71 DirectoryImpl::DirectoryImpl(InterfaceRequest<Directory> request, | |
72 base::ScopedFD dir_fd, | |
73 const base::FilePath& owned_dir_name) | |
74 : binding_(this, request.Pass()), | |
75 dir_fd_(dir_fd.Pass()), | |
76 owned_dir_name_(owned_dir_name) { | |
77 DCHECK(dir_fd_.is_valid()); | |
78 } | |
79 | |
80 DirectoryImpl::~DirectoryImpl() { | |
81 if (!owned_dir_name_.empty()) { | |
82 DVLOG(1) << "Deleting owned directory: " << owned_dir_name_.value(); | |
83 LOG_IF(ERROR, !base::DeleteFile(owned_dir_name_, true)) | |
84 << "Failed to delete owned directory: " << owned_dir_name_.value(); | |
85 } | |
86 } | |
87 | |
88 void DirectoryImpl::Read( | |
89 const Callback<void(Error, Array<DirectoryEntryPtr>)>& callback) { | |
90 // TODO(vtl): FIXME sooner | |
91 NOTIMPLEMENTED(); | |
92 callback.Run(ERROR_UNIMPLEMENTED, Array<DirectoryEntryPtr>()); | |
93 } | |
94 | |
95 void DirectoryImpl::Stat( | |
96 const Callback<void(Error, FileInformationPtr)>& callback) { | |
97 // TODO(vtl): FIXME sooner | |
98 NOTIMPLEMENTED(); | |
99 callback.Run(ERROR_UNIMPLEMENTED, nullptr); | |
100 } | |
101 | |
102 void DirectoryImpl::Touch(TimespecOrNowPtr atime, | |
103 TimespecOrNowPtr mtime, | |
104 const Callback<void(Error)>& callback) { | |
105 // TODO(vtl): FIXME sooner | |
106 NOTIMPLEMENTED(); | |
107 callback.Run(ERROR_UNIMPLEMENTED); | |
108 } | |
109 | |
110 // TODO(vtl): Move the implementation to a thread pool. | |
111 void DirectoryImpl::OpenFile(const String& path, | |
112 InterfaceRequest<File> file, | |
113 uint32_t open_flags, | |
114 const Callback<void(Error)>& callback) { | |
115 DCHECK(!path.is_null()); | |
116 DCHECK(dir_fd_.is_valid()); | |
117 | |
118 if (Error error = IsPathValid(path)) { | |
119 callback.Run(error); | |
120 return; | |
121 } | |
122 // TODO(vtl): Make sure the path doesn't exit this directory (if appropriate). | |
123 // TODO(vtl): Maybe allow absolute paths? | |
124 | |
125 if (Error error = ValidateOpenFlags(open_flags, false)) { | |
126 callback.Run(error); | |
127 return; | |
128 } | |
129 | |
130 int flags = 0; | |
131 if ((open_flags & kOpenFlagRead)) | |
132 flags |= (open_flags & kOpenFlagWrite) ? O_RDWR : O_RDONLY; | |
133 else | |
134 flags |= O_WRONLY; | |
135 if ((open_flags & kOpenFlagCreate)) | |
136 flags |= O_CREAT; | |
137 if ((open_flags & kOpenFlagExclusive)) | |
138 flags |= O_EXCL; | |
139 if ((open_flags & kOpenFlagAppend)) | |
140 flags |= O_APPEND; | |
141 if ((open_flags & kOpenFlagTruncate)) | |
142 flags |= O_TRUNC; | |
143 | |
144 base::ScopedFD file_fd( | |
145 HANDLE_EINTR(openat(dir_fd_.get(), path.get().c_str(), flags, 0600))); | |
146 if (!file_fd.is_valid()) { | |
147 callback.Run(ErrnoToError(errno)); | |
148 return; | |
149 } | |
150 | |
151 if (file.is_pending()) | |
152 new FileImpl(file.Pass(), file_fd.Pass()); | |
153 callback.Run(ERROR_OK); | |
154 } | |
155 | |
156 void DirectoryImpl::OpenDirectory(const String& path, | |
157 InterfaceRequest<Directory> directory, | |
158 uint32_t open_flags, | |
159 const Callback<void(Error)>& callback) { | |
160 // TODO(vtl): FIXME sooner | |
161 NOTIMPLEMENTED(); | |
162 callback.Run(ERROR_UNIMPLEMENTED); | |
163 } | |
164 | |
165 void DirectoryImpl::Rename(const String& path, | |
166 const String& new_path, | |
167 const Callback<void(Error)>& callback) { | |
168 DCHECK(!path.is_null()); | |
169 DCHECK(!new_path.is_null()); | |
170 DCHECK(dir_fd_.is_valid()); | |
171 | |
172 if (Error error = IsPathValid(path)) { | |
173 callback.Run(error); | |
174 return; | |
175 } | |
176 if (Error error = IsPathValid(new_path)) { | |
177 callback.Run(error); | |
178 return; | |
179 } | |
180 // TODO(vtl): see TODOs about |path| in OpenFile() | |
181 | |
182 if (renameat(dir_fd_.get(), path.get().c_str(), dir_fd_.get(), | |
183 new_path.get().c_str())) { | |
184 callback.Run(ErrnoToError(errno)); | |
185 return; | |
186 } | |
187 | |
188 callback.Run(ERROR_OK); | |
189 } | |
190 | |
191 void DirectoryImpl::Delete(const String& path, | |
192 uint32_t delete_flags, | |
193 const Callback<void(Error)>& callback) { | |
194 // TODO(vtl): FIXME sooner | |
195 NOTIMPLEMENTED(); | |
196 callback.Run(ERROR_UNIMPLEMENTED); | |
197 } | |
198 | |
199 } // namespace files | |
200 } // namespace mojo | |
OLD | NEW |