vfs: check userland buffers before reading them.
[haiku.git] / src / build / libroot / fs_attr_haiku.cpp
blob0a931a2f6dc52463975bf43ad446cc4597acdd7e
1 /*
2 * Copyright 2017, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
6 /*! Shim over the host Haiku fs_attr API */
8 #define BUILDING_FS_ATTR_HAIKU
9 // so build fs_attr.h will not shadow the fs*attr functions
12 #ifdef BUILDING_FS_SHELL
13 # include "compat.h"
14 # define B_OK 0
15 # define B_BAD_VALUE EINVAL
16 # define B_FILE_ERROR EBADF
17 # define B_ERROR EINVAL
18 # define B_ENTRY_NOT_FOUND ENOENT
19 # define B_NO_MEMORY ENOMEM
20 #else
21 # include <syscalls.h>
23 # include "fs_impl.h"
24 # include "fs_descriptors.h"
25 #endif
27 #include <dirent.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <sys/stat.h>
35 #include <map>
36 #include <string>
38 #include <fs_attr.h>
41 namespace BPrivate {}
42 using namespace BPrivate;
45 namespace {
47 // LocalFD
48 #include "LocalFD.h"
50 } // unnamed namspace
53 // # pragma mark - Public API
56 // fs_open_attr_dir
57 extern "C" DIR *
58 build_fs_open_attr_dir(const char *path)
60 return fs_open_attr_dir(path);
63 // fs_fopen_attr_dir
64 extern "C" DIR* fs_lopen_attr_dir(const char *path);
65 extern "C" DIR*
66 build_fs_fopen_attr_dir(int fd)
68 LocalFD localFD;
69 status_t error = localFD.Init(fd);
70 if (error != B_OK) {
71 errno = error;
72 return NULL;
75 if (localFD.FD() < 0) {
76 return fs_lopen_attr_dir(localFD.Path());
77 } else {
78 return fs_fopen_attr_dir(localFD.FD());
82 // fs_close_attr_dir
83 extern "C" int
84 build_fs_close_attr_dir(DIR *dir)
86 return fs_close_attr_dir(dir);
89 // fs_read_attr_dir
90 extern "C" struct dirent *
91 build_fs_read_attr_dir(DIR *dir)
93 return fs_read_attr_dir(dir);
96 // fs_rewind_attr_dir
97 extern "C" void
98 build_fs_rewind_attr_dir(DIR *dir)
100 return fs_rewind_attr_dir(dir);
103 // fs_fopen_attr
104 extern "C" int
105 build_fs_fopen_attr(int fd, const char *attribute, uint32 type, int openMode)
107 if (fd < 0) {
108 errno = B_BAD_VALUE;
109 return -1;
112 LocalFD localFD;
113 status_t error = localFD.Init(fd);
114 if (error != B_OK) {
115 errno = error;
116 return -1;
119 if (localFD.FD() < 0) {
120 return fs_open_attr(localFD.Path(), attribute, type,
121 openMode | O_NOTRAVERSE);
122 } else {
123 return fs_fopen_attr(localFD.FD(), attribute, type, openMode);
127 // fs_close_attr
128 extern "C" int
129 build_fs_close_attr(int fd)
131 return fs_close_attr(fd);
134 // fs_read_attr
135 extern "C" ssize_t
136 build_fs_read_attr(int fd, const char* attribute, uint32 type, off_t pos,
137 void *buffer, size_t readBytes)
139 LocalFD localFD;
140 status_t error = localFD.Init(fd);
141 if (error != B_OK) {
142 errno = error;
143 return -1;
146 ssize_t bytesRead;
147 if (localFD.FD() < 0) {
148 int fd = open(localFD.Path(), O_RDONLY | O_NOTRAVERSE);
149 bytesRead = fs_read_attr(fd, attribute, type,
150 pos, buffer, readBytes);
151 close(fd);
152 } else {
153 bytesRead = fs_read_attr(localFD.FD(), attribute, type,
154 pos, buffer, readBytes);
156 if (bytesRead < 0) {
157 // Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute
158 // doesn't exist.
159 if (errno == ENOATTR || errno == ENODATA)
160 errno = B_ENTRY_NOT_FOUND;
161 return -1;
164 return bytesRead;
167 // fs_write_attr
168 extern "C" ssize_t
169 build_fs_write_attr(int fd, const char* attribute, uint32 type, off_t pos,
170 const void *buffer, size_t writeBytes)
172 LocalFD localFD;
173 status_t error = localFD.Init(fd);
174 if (error != B_OK) {
175 errno = error;
176 return -1;
179 ssize_t written;
180 if (localFD.FD() < 0) {
181 int fd = open(localFD.Path(), O_NOTRAVERSE | O_WRONLY);
182 written = fs_write_attr(fd, attribute, type,
183 pos, buffer, writeBytes);
184 close(fd);
185 } else {
186 written = fs_write_attr(localFD.FD(), attribute, type,
187 pos, buffer, writeBytes);
190 return written;
193 // fs_remove_attr
194 extern "C" int
195 build_fs_remove_attr(int fd, const char* attribute)
197 LocalFD localFD;
198 status_t error = localFD.Init(fd);
199 if (error != B_OK) {
200 errno = error;
201 return -1;
204 // remove attribute
205 int result;
206 if (localFD.FD() < 0) {
207 int fd = open(localFD.Path(), O_NOTRAVERSE | O_WRONLY);
208 result = fs_remove_attr(fd, attribute);
209 close(fd);
210 } else {
211 result = fs_remove_attr(localFD.FD(), attribute);
214 if (result < 0) {
215 // Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute
216 // doesn't exist.
217 if (errno == ENOATTR || errno == ENODATA)
218 errno = B_ENTRY_NOT_FOUND;
219 return -1;
221 return 0;
224 // fs_stat_attr
225 extern "C" int
226 build_fs_stat_attr(int fd, const char *attribute, struct attr_info *attrInfo)
228 if (!attribute || !attrInfo) {
229 errno = B_BAD_VALUE;
230 return -1;
233 LocalFD localFD;
234 status_t error = localFD.Init(fd);
235 if (error != B_OK) {
236 errno = error;
237 return -1;
240 int result;
241 if (localFD.FD() < 0) {
242 int fd = open(localFD.Path(), O_NOTRAVERSE | O_RDONLY);
243 result = fs_stat_attr(fd, attribute, attrInfo);
244 close(fd);
245 } else {
246 result = fs_stat_attr(localFD.FD(), attribute, attrInfo);
249 return result;
253 // #pragma mark - Private Syscalls
256 #ifndef BUILDING_FS_SHELL
258 // _kern_open_attr_dir
260 _kern_open_attr_dir(int fd, const char *path)
262 // get node ref for the node
263 struct stat st;
264 status_t error = _kern_read_stat(fd, path, false, &st,
265 sizeof(struct stat));
266 if (error != B_OK) {
267 errno = error;
268 return -1;
270 NodeRef ref(st);
272 DIR* dir;
273 if (path) {
274 // If a path was given, get a usable path.
275 string realPath;
276 status_t error = get_path(fd, path, realPath);
277 if (error != B_OK)
278 return error;
280 dir = build_fs_open_attr_dir(realPath.c_str());
281 } else
282 dir = build_fs_fopen_attr_dir(fd);
284 if (!dir)
285 return errno;
287 // create descriptor
288 AttrDirDescriptor *descriptor = new AttrDirDescriptor(dir, ref);
289 return add_descriptor(descriptor);
292 // _kern_rename_attr
293 status_t
294 _kern_rename_attr(int fromFile, const char *fromName, int toFile,
295 const char *toName)
297 // not supported ATM
298 return B_BAD_VALUE;
301 // _kern_remove_attr
302 status_t
303 _kern_remove_attr(int fd, const char *name)
305 if (!name)
306 return B_BAD_VALUE;
308 if (build_fs_remove_attr(fd, name) < 0)
309 return errno;
310 return B_OK;
313 #endif // ! BUILDING_FS_SHELL