1/* 2 * Copyright 2017, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6/*! Shim over the host Haiku fs_attr API */ 7 8 9#ifdef BUILDING_FS_SHELL 10# include "compat.h" 11# define B_OK 0 12# define B_BAD_VALUE EINVAL 13# define B_FILE_ERROR EBADF 14# define B_ERROR EINVAL 15# define B_ENTRY_NOT_FOUND ENOENT 16# define B_NO_MEMORY ENOMEM 17#else 18# include <syscalls.h> 19 20# include "fs_impl.h" 21# include "fs_descriptors.h" 22#endif 23 24#include <dirent.h> 25#include <errno.h> 26#include <fcntl.h> 27#include <stdio.h> 28#include <stdlib.h> 29#include <unistd.h> 30#include <sys/stat.h> 31 32#include <map> 33#include <string> 34 35#include <fs_attr.h> 36 37 38namespace BPrivate {} 39using namespace BPrivate; 40 41 42namespace { 43 44// LocalFD 45#include "LocalFD.h" 46 47} // unnamed namspace 48 49 50// # pragma mark - Public API 51 52 53// fs_open_attr_dir 54extern "C" DIR * 55_haiku_build_fs_open_attr_dir(const char *path) 56{ 57 return fs_open_attr_dir(path); 58} 59 60// fs_lopen_attr_dir 61extern "C" DIR* 62_haiku_build_fs_lopen_attr_dir(const char *path) 63{ 64 return fs_lopen_attr_dir(path); 65} 66 67// fs_fopen_attr_dir 68extern "C" DIR* 69_haiku_build_fs_fopen_attr_dir(int fd) 70{ 71 LocalFD localFD; 72 status_t error = localFD.Init(fd); 73 if (error != B_OK) { 74 errno = error; 75 return NULL; 76 } 77 78 if (localFD.FD() < 0) { 79 return fs_lopen_attr_dir(localFD.Path()); 80 } else { 81 return fs_fopen_attr_dir(localFD.FD()); 82 } 83} 84 85// fs_close_attr_dir 86extern "C" int 87_haiku_build_fs_close_attr_dir(DIR *dir) 88{ 89 return fs_close_attr_dir(dir); 90} 91 92// fs_read_attr_dir 93extern "C" struct dirent * 94_haiku_build_fs_read_attr_dir(DIR *dir) 95{ 96 return fs_read_attr_dir(dir); 97} 98 99// fs_rewind_attr_dir 100extern "C" void 101_haiku_build_fs_rewind_attr_dir(DIR *dir) 102{ 103 return fs_rewind_attr_dir(dir); 104} 105 106// fs_fopen_attr 107extern "C" int 108_haiku_build_fs_fopen_attr(int fd, const char *attribute, uint32 type, int openMode) 109{ 110 if (fd < 0) { 111 errno = B_BAD_VALUE; 112 return -1; 113 } 114 115 LocalFD localFD; 116 status_t error = localFD.Init(fd); 117 if (error != B_OK) { 118 errno = error; 119 return -1; 120 } 121 122 if (localFD.FD() < 0) { 123 return fs_open_attr(localFD.Path(), attribute, type, 124 openMode | O_NOTRAVERSE); 125 } else { 126 return fs_fopen_attr(localFD.FD(), attribute, type, openMode); 127 } 128} 129 130// fs_close_attr 131extern "C" int 132_haiku_build_fs_close_attr(int fd) 133{ 134 return fs_close_attr(fd); 135} 136 137// fs_read_attr 138extern "C" ssize_t 139_haiku_build_fs_read_attr(int fd, const char* attribute, uint32 type, off_t pos, 140 void *buffer, size_t readBytes) 141{ 142 LocalFD localFD; 143 status_t error = localFD.Init(fd); 144 if (error != B_OK) { 145 errno = error; 146 return -1; 147 } 148 149 ssize_t bytesRead; 150 if (localFD.FD() < 0) { 151 int fd = open(localFD.Path(), O_RDONLY | O_NOTRAVERSE); 152 bytesRead = fs_read_attr(fd, attribute, type, 153 pos, buffer, readBytes); 154 close(fd); 155 } else { 156 bytesRead = fs_read_attr(localFD.FD(), attribute, type, 157 pos, buffer, readBytes); 158 } 159 if (bytesRead < 0) { 160 // Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute 161 // doesn't exist. 162 if (errno == ENOATTR || errno == ENODATA) 163 errno = B_ENTRY_NOT_FOUND; 164 return -1; 165 } 166 167 return bytesRead; 168} 169 170// fs_write_attr 171extern "C" ssize_t 172_haiku_build_fs_write_attr(int fd, const char* attribute, uint32 type, off_t pos, 173 const void *buffer, size_t writeBytes) 174{ 175 LocalFD localFD; 176 status_t error = localFD.Init(fd); 177 if (error != B_OK) { 178 errno = error; 179 return -1; 180 } 181 182 ssize_t written; 183 if (localFD.FD() < 0) { 184 int fd = open(localFD.Path(), O_NOTRAVERSE | O_WRONLY); 185 written = fs_write_attr(fd, attribute, type, 186 pos, buffer, writeBytes); 187 close(fd); 188 } else { 189 written = fs_write_attr(localFD.FD(), attribute, type, 190 pos, buffer, writeBytes); 191 } 192 193 return written; 194} 195 196// fs_remove_attr 197extern "C" int 198_haiku_build_fs_remove_attr(int fd, const char* attribute) 199{ 200 LocalFD localFD; 201 status_t error = localFD.Init(fd); 202 if (error != B_OK) { 203 errno = error; 204 return -1; 205 } 206 207 // remove attribute 208 int result; 209 if (localFD.FD() < 0) { 210 int fd = open(localFD.Path(), O_NOTRAVERSE | O_WRONLY); 211 result = fs_remove_attr(fd, attribute); 212 close(fd); 213 } else { 214 result = fs_remove_attr(localFD.FD(), attribute); 215 } 216 217 if (result < 0) { 218 // Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute 219 // doesn't exist. 220 if (errno == ENOATTR || errno == ENODATA) 221 errno = B_ENTRY_NOT_FOUND; 222 return -1; 223 } 224 return 0; 225} 226 227// fs_stat_attr 228extern "C" int 229_haiku_build_fs_stat_attr(int fd, const char *attribute, struct attr_info *attrInfo) 230{ 231 if (!attribute || !attrInfo) { 232 errno = B_BAD_VALUE; 233 return -1; 234 } 235 236 LocalFD localFD; 237 status_t error = localFD.Init(fd); 238 if (error != B_OK) { 239 errno = error; 240 return -1; 241 } 242 243 int result; 244 if (localFD.FD() < 0) { 245 int fd = open(localFD.Path(), O_NOTRAVERSE | O_RDONLY); 246 result = fs_stat_attr(fd, attribute, attrInfo); 247 close(fd); 248 } else { 249 result = fs_stat_attr(localFD.FD(), attribute, attrInfo); 250 } 251 252 return result; 253} 254 255 256// #pragma mark - Private Syscalls 257 258 259#ifndef BUILDING_FS_SHELL 260 261// _kern_open_attr_dir 262int 263_kern_open_attr_dir(int fd, const char *path) 264{ 265 // get node ref for the node 266 struct stat st; 267 status_t error = _kern_read_stat(fd, path, false, &st, 268 sizeof(struct stat)); 269 if (error != B_OK) { 270 errno = error; 271 return -1; 272 } 273 NodeRef ref(st); 274 275 DIR* dir; 276 if (path) { 277 // If a path was given, get a usable path. 278 string realPath; 279 status_t error = get_path(fd, path, realPath); 280 if (error != B_OK) 281 return error; 282 283 dir = _haiku_build_fs_open_attr_dir(realPath.c_str()); 284 } else 285 dir = _haiku_build_fs_fopen_attr_dir(fd); 286 287 if (!dir) 288 return errno; 289 290 // create descriptor 291 AttrDirDescriptor *descriptor = new AttrDirDescriptor(dir, ref); 292 return add_descriptor(descriptor); 293} 294 295// _kern_rename_attr 296status_t 297_kern_rename_attr(int fromFile, const char *fromName, int toFile, 298 const char *toName) 299{ 300 // not supported ATM 301 return B_BAD_VALUE; 302} 303 304// _kern_remove_attr 305status_t 306_kern_remove_attr(int fd, const char *name) 307{ 308 if (!name) 309 return B_BAD_VALUE; 310 311 if (_haiku_build_fs_remove_attr(fd, name) < 0) 312 return errno; 313 return B_OK; 314} 315 316#endif // ! BUILDING_FS_SHELL 317