diff --git a/headers/private/storage/kernel_interface.h b/headers/private/storage/kernel_interface.h deleted file mode 100644 index 6418f10625..0000000000 --- a/headers/private/storage/kernel_interface.h +++ /dev/null @@ -1,357 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the OpenBeOS license. -//--------------------------------------------------------------------- -/*! - \file kernel_interface.h - This is the private interface used by the Storage Kit - to communicate with the kernel -*/ - -#ifndef _STORAGE_KIT_KERNEL_INTERFACE_H -#define _STORAGE_KIT_KERNEL_INTERFACE_H - -#include -#include - -// For typedefs -#include // For dirent -#include // For struct stat -#include // For flock -#include // File sytem information functions, structs, defines - -// Forward Declarations -typedef struct attr_info; -typedef struct entry_ref; - -//! Private Storage Kit Namespace -/*! Encompasses the functions used internally by the Storage Kit to - interface with the kernel, as well as various internal support functions, - data types, and type aliases. */ -namespace BPrivate { -namespace Storage { - -// Type aliases -typedef dirent DirEntry; -typedef struct flock FileLock; -typedef struct stat Stat; -typedef uint32 StatMember; -typedef attr_info AttrInfo; -typedef int OpenFlags; // open() flags -typedef mode_t CreationFlags; // open() mode -typedef int SeekMode; // lseek() mode - -// For convenience: -struct LongDirEntry : DirEntry { char _buffer[B_FILE_NAME_LENGTH]; }; - -// Constants -- POSIX versions -const FileDescriptor NullFd = -1; - - -//------------------------------------------------------------------------------ -// Device Functions -//------------------------------------------------------------------------------ -/*! Returns information about the file system on the specified device. */ -status_t stat_dev(dev_t dev, fs_info* info); - - -//------------------------------------------------------------------------------ -// File Functions -//------------------------------------------------------------------------------ -/*! \brief Opens the filesystem entry specified by path. - - Returns a - new file descriptor if successful, -1 otherwise. This version - fails if the given file does not exist, or if you specify - O_CREAT as one of the flags (use the four argument version - of BPrivate::Storage::open() if you wish to create the file when - it doesn't already exist). */ -status_t open(const char *path, OpenFlags flags, FileDescriptor &result); - -/*! \brief Same as the first version, but tries to open read-only, if - first the attempt failed with B_READ_ONLY_DEVICE or - B_PERMISSION_DENIED and \a fallBackToReadOnly is \c true. -*/ -status_t open(const char *path, OpenFlags flags, FileDescriptor &result, - bool fallBackToReadOnly); - -/*! \brief Same as the first version of open() except the file is created with the - permissions given by creationFlags if it doesn't exist. */ -status_t open(const char *path, OpenFlags flags, CreationFlags creationFlags, - FileDescriptor &result); - -/*! \brief Same as the third version, but tries to open read-only, if - first the attempt failed with B_READ_ONLY_DEVICE or - B_PERMISSION_DENIED and \a fallBackToReadOnly is \c true. -*/ -status_t open(const char *path, OpenFlags flags, CreationFlags creationFlags, - FileDescriptor &result, bool fallBackToReadOnly); - -/*! \brief Closes a previously open()ed file. */ -status_t close( FileDescriptor file ); - -//! Reads data from a file into a buffer. -ssize_t read(FileDescriptor fd, void *buf, size_t len); - -//! Reads data from a certain position in a file into a buffer. -ssize_t read(FileDescriptor fd, void *buf, off_t pos, size_t len); - -//! Writes data from a buffer into a file. -ssize_t write(FileDescriptor fd, const void *buf, size_t len); - -//! Writes data from a buffer to a certain position in a file. -ssize_t write(FileDescriptor fd, const void *buf, off_t pos, size_t len); - -//! Moves a file's read/write pointer. -off_t seek(FileDescriptor fd, off_t pos, SeekMode mode); - -//! Returns the position of a file's read/write pointer. -off_t get_position(FileDescriptor fd); - -/*! \brief Returns a new file descriptor that refers to the same file as - that specified, or -1 if unsuccessful. Remember to call close - on the file descriptor when through with it. */ -FileDescriptor dup(FileDescriptor file); - -/*! \brief Similar to the first version, aside from that an error code is - returned and the resulting file descriptor is passed back via a reference - parameter. */ -status_t dup(FileDescriptor file, FileDescriptor& result); - -/*! \brief Flushes any buffers associated with the given file to disk - and then returns. */ -status_t sync(FileDescriptor file); - -//! Locks the given file so it may not be accessed by anyone else. -status_t lock(FileDescriptor file, OpenFlags mode, FileLock *lock); - -//! Unlocks a file previously locked with lock(). -status_t unlock(FileDescriptor file, FileLock *lock); - -//! Returns statistical information for the given file. -status_t get_stat(const char *path, Stat *s); -status_t get_stat(FileDescriptor file, Stat *s); -status_t get_stat(entry_ref &ref, Stat *s); - -//! Modifies a given portion of the file's statistical information. -status_t set_stat(FileDescriptor file, Stat &s, StatMember what); - -//! Same as the other version of set_stat(), except the file is specified by name. -status_t set_stat(const char *filename, Stat &s, StatMember what); - -//------------------------------------------------------------------------------ -// Attribute Functions -//------------------------------------------------------------------------------ -/*! \brief Reads the data from the specified attribute into the given buffer of size - count. Returns the number of bytes actually read. */ -ssize_t read_attr(FileDescriptor file, const char *attribute, uint32 type, - off_t pos, void *buf, size_t count ); - -//! Write count bytes from the given data buffer into the specified attribute. -ssize_t write_attr(FileDescriptor file, const char *attribute, uint32 type, - off_t pos, const void *buf, size_t count); - -//! Renames the specified attribute. -status_t rename_attr(FileDescriptor file, const char *oldName, - const char *newName); - -//! Removes the specified attribute and any data associated with it. -status_t remove_attr(FileDescriptor file, const char *attr); - -//! Returns statistical information about the given attribute. */ -status_t stat_attr(FileDescriptor file, const char *name, AttrInfo *ai); - - - -//------------------------------------------------------------------------------ -// Attribute Directory Functions -//------------------------------------------------------------------------------ -/*! Opens the attribute directory of a given file. */ -status_t open_attr_dir(FileDescriptor file, FileDescriptor &result); - -/*! Rewinds the given attribute directory. */ -status_t rewind_attr_dir(FileDescriptor dir); - -/*! Returns the next item in the given attribute directory, or - B_ENTRY_NOT_FOUND if at the end of the list. */ -status_t read_attr_dir(FileDescriptor dir, DirEntry &buffer); - -/*! Closes an attribute directory previously opened with open_attr_dir(). */ -status_t close_attr_dir(FileDescriptor dir); - - -//------------------------------------------------------------------------------ -// Directory Functions -//------------------------------------------------------------------------------ -/*! \brief Opens the given directory. Sets result to a properly "unitialized" directory - if the function fails. */ -status_t open_dir(const char *path, FileDescriptor &result); - -//! Creates a new directory. -status_t create_dir(const char *path, - mode_t mode = S_IRWXU | S_IRWXG | S_IRWXU); - -//! Creates a new directory and opens it. -status_t create_dir(const char *path, FileDescriptor &result, - mode_t mode = S_IRWXU | S_IRWXG | S_IRWXU); - -//! Returns the next entries in the given directory. -int32 read_dir(FileDescriptor dir, DirEntry *buffer, size_t length, - int32 count = INT_MAX); - -/*! Rewindes the directory to the first entry in the list. */ -status_t rewind_dir(FileDescriptor dir); - -/*! Iterates through the given directory searching for an entry whose name - matches that given by name. On success, places the DirEntry in result - and returns B_OK. On failures, returns an error code and sets result to - BPrivate::Storage::NullDir. - - Note: This call modifies the internal position marker of dir. */ -status_t find_dir(FileDescriptor dir, const char *name, DirEntry *result, - size_t length); - -/*! Calls the other version of BPrivate::Storage::find_dir() and stores the results - in the given entry_ref. */ -status_t find_dir(FileDescriptor dir, const char *name, entry_ref *result); - -/*! Creates a duplicated of the given directory and places it in result if successful, - returning B_OK. Returns an error code and sets result to -1 if - unsuccessful. */ -status_t dup_dir(FileDescriptor dir, FileDescriptor &result); - -/*! Closes the given directory. */ -status_t close_dir(FileDescriptor dir); - -//------------------------------------------------------------------------------ -// SymLink functions -//------------------------------------------------------------------------------ -//! Creates a new symbolic link. -status_t create_link(const char *path, const char *linkToPath); - -//! Creates a new symbolic link and opens it. -status_t create_link(const char *path, const char *linkToPath, - FileDescriptor &result); - -/*! If path refers to a symlink, the pathname of the target to which path - is linked is copied into result and NULL terminated, if the buffer is - long enough, the path is being truncated at size chars if necessary - (a buffer of size B_PATH_NAME_LENGTH is a good idea), and the number of - chars in the target pathname is returned. If size is less than 1 or result - is NULL, B_BAD_VALUE will be returned and result will remain unmodified. - For any other error, result is set to an empty string and an error code - is returned. */ -ssize_t read_link(const char *path, char *result, size_t size); - -/*! Similar to the first version. Instead of a path name, a file descriptor - of the symbolic link is supplied. -*/ -ssize_t read_link(FileDescriptor fd, char *result, size_t size); - - -//------------------------------------------------------------------------------ -// Query Functions -//------------------------------------------------------------------------------ -/*! \brief Opens a query. Sets result to a properly "unitialized" query - if the function fails. */ -status_t open_query(dev_t device, const char *query, uint32 flags, - FileDescriptor &result); - -/*! \brief Opens a live query. Sets result to a properly "unitialized" query - if the function fails. */ -status_t open_live_query(dev_t device, const char *query, uint32 flags, - port_id port, int32 token, FileDescriptor &result); - -//! Returns the next entries in the given query. -int32 read_query(FileDescriptor query, DirEntry *buffer, size_t length, - int32 count = INT_MAX); - -/*! Closes the given query. */ -status_t close_query(FileDescriptor dir); - - -//------------------------------------------------------------------------------ -// Miscellaneous Functions -//------------------------------------------------------------------------------ -/*! Converts the given entry_ref into an absolute pathname, returning - the result in the string of length size pointed to by result (a size - of B_PATH_NAME_LENGTH is a good idea). - - Returns B_OK if successful. - - If ref or result is NULL, B_BAD_VALUE is returned. Otherwise, - an error code is returned. The state of result after an error is undefined. -*/ -status_t entry_ref_to_path(const struct entry_ref *ref, char *result, - size_t size); - -/*! See the other definition of entry_ref_to_path() */ -status_t entry_ref_to_path(dev_t device, ino_t directory, const char *name, - char *result, size_t size); - -/*! Converts the given directory into an entry_ref. Note that the entry_ref is - actually a reference to the file "." in the given directory. - - Returns B_OK if successful. - - If dir is < 0 or result is NULL, B_BAD_VALUE is returned. - Otherwise, an appropriate error code is returned. - */ -status_t dir_to_self_entry_ref(FileDescriptor dir, entry_ref *result); - - -/*! Converts the given directory into an absolute pathname, returning the - result in the string of length size pointed to by result (a size of - B_PATH_NAME_LENGTH is a good idea). - - Returns B_OK if successful. - - If dir is < 0 or result is NULL, B_BAD_VALUE - is returned. Otherwise, an error code is returned. The state of result after - an error is undefined. -*/ -status_t dir_to_path( FileDescriptor dir, char *result, size_t size ); - -/*! \brief Returns the canonical representation of a given path referring to an - potentially abstract entry in an existing directory. */ -status_t get_canonical_path(const char *path, char *result, size_t size); - -/*! \brief Returns the canonical representation of a given path referring to an - potentially abstract entry in an existing directory. */ -status_t get_canonical_path(const char *path, char *&result); - -/*! \brief Returns the canonical representation of a given path referring to an - existing directory. */ -status_t get_canonical_dir_path(const char *path, char *result, size_t size); - -/*! \brief Returns the canonical representation of a given path referring to an - existing directory. */ -status_t get_canonical_dir_path(const char *path, char *&result); - -/*! \brief Returns the path of this application. - The supplied buffer must be at least B_PATH_NAME_LENGTH + 1 bytes long. - The result will be null terminated. -*/ -status_t get_app_path(char *buffer); - -/*! Returns true if the given entry_ref represents the root directory, false otherwise. */ -bool entry_ref_is_root_dir(const entry_ref *ref); - -//! Returns true if the given device is the root device, false otherwise -bool device_is_root_device(dev_t device); - -/*! Renames oldPath to newPath, replacing newPath if it exists. */ -status_t rename(const char *oldPath, const char *newPath); - -/*! Removes path from the filesystem. */ -status_t remove(const char *path); - -//! Sets the name of a volume. -status_t set_volume_name(dev_t device, const char *name); - -}; // namespace Storage -}; // namespace BPrivate - -#endif // _STORAGE_KIT_KERNEL_INTERFACE_H - - diff --git a/src/kits/storage/kernel_interface.POSIX.cpp b/src/kits/storage/kernel_interface.POSIX.cpp deleted file mode 100644 index 2dc1bca9d1..0000000000 --- a/src/kits/storage/kernel_interface.POSIX.cpp +++ /dev/null @@ -1,1241 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the OpenBeOS license. -//---------------------------------------------------------------------- -/*! - \file kernel_interface.POSIX.cpp - Initial implementation of our kernel interface with - calls to the POSIX api. This will later be replaced with a version - that makes syscalls into the actual kernel -*/ - -#include "kernel_interface.h" -#include "storage_support.h" - -#include -#include // used by get_app_path() -#include // File sytem information functions, structs, defines -#include // BeOS's C-based attribute functions -#include // BeOS's C-based query functions -#include // entry_ref - -#include -#include - -#include -#include -#include -#include -#include - -// This is just for cout while developing; shouldn't need it -// when all is said and done. -#include - -using namespace std; - -// For convenience: -struct LongDIR : DIR { char _buffer[B_FILE_NAME_LENGTH]; }; - - -//------------------------------------------------------------------------------ -// Device Functions -//------------------------------------------------------------------------------ -/*! Returns information about the file system on the specified device. */ - -status_t -BPrivate::Storage::stat_dev(dev_t dev, fs_info* info) -{ - return fs_stat_dev(dev, info); -} - - -//------------------------------------------------------------------------------ -// File Functions -//------------------------------------------------------------------------------ - -status_t -BPrivate::Storage::open( const char *path, OpenFlags flags, FileDescriptor &result ) -{ - if (path == NULL) { - result = -1; - return B_BAD_VALUE; - } - - // This version of the function may not be called with the O_CREAT flag - if (flags & O_CREAT) - return B_BAD_VALUE; - - // Open file and return the proper error code - result = ::open(path, flags); - return (result == -1) ? errno : B_OK ; -} - -status_t -BPrivate::Storage::open( const char *path, OpenFlags flags, - FileDescriptor &result, bool fallBackToReadOnly ) -{ - status_t error = open(path, flags, result); - if (error == B_READ_ONLY_DEVICE || error == B_PERMISSION_DENIED - && fallBackToReadOnly && (flags & O_RWMASK == O_RDWR)) { - flags = flags & ~O_RWMASK | O_RDONLY; - error = open(path, flags, result); - } - return error; -} - -/*! Same as the other version of open() except the file is created with the - permissions given by creationFlags if it doesn't exist. */ -status_t -BPrivate::Storage::open( const char *path, OpenFlags flags, - CreationFlags creationFlags, FileDescriptor &result ) -{ - if (path == NULL) { - result = -1; - return B_BAD_VALUE; - } - - // Open/Create the file and return the proper error code - result = ::open(path, flags | O_CREAT, creationFlags); - return (result == -1) ? errno : B_OK ; -} - -status_t -BPrivate::Storage::open( const char *path, OpenFlags flags, - CreationFlags creationFlags, FileDescriptor &result, - bool fallBackToReadOnly ) -{ - status_t error = open(path, flags, creationFlags, result); - if (error == B_READ_ONLY_DEVICE || error == B_PERMISSION_DENIED - && fallBackToReadOnly && (flags & O_RWMASK == O_RDWR)) { - flags = flags & ~O_RWMASK | O_RDONLY; - error = open(path, flags, creationFlags, result); - } - return error; -} - -status_t -BPrivate::Storage::close(BPrivate::Storage::FileDescriptor file) -{ - return (::close(file) == -1) ? errno : B_OK ; -} - -/*! \param fd the file descriptor - \param buf the buffer to be read into - \param len the number of bytes to be read - \return the number of bytes actually read or an error code -*/ -ssize_t -BPrivate::Storage::read(BPrivate::Storage::FileDescriptor fd, void *buf, size_t len) -{ - ssize_t result = (buf == NULL ? B_BAD_VALUE : B_OK); - if (result == B_OK) { - result = ::read(fd, buf, len); - if (result == -1) - result = errno; - } - return result; -} - -/*! \param fd the file descriptor - \param buf the buffer to be read into - \param pos file position from which to be read - \param len the number of bytes to be read - \return the number of bytes actually read or an error code -*/ -ssize_t -BPrivate::Storage::read(BPrivate::Storage::FileDescriptor fd, void *buf, off_t pos, - size_t len) -{ - ssize_t result = (buf == NULL || pos < 0 ? B_BAD_VALUE : B_OK); - if (result == B_OK) { - result = ::read_pos(fd, pos, buf, len); - if (result == -1) - result = errno; - } - return result; -} - -/*! \param fd the file descriptor - \param buf the buffer containing the data to be written - \param len the number of bytes to be written - \return the number of bytes actually written or an error code -*/ -ssize_t -BPrivate::Storage::write(BPrivate::Storage::FileDescriptor fd, const void *buf, size_t len) -{ - ssize_t result = (buf == NULL ? B_BAD_VALUE : B_OK); - if (result == B_OK) { - result = ::write(fd, buf, len); - if (result == -1) - result = errno; - } - return result; -} - -/*! \param fd the file descriptor - \param buf the buffer containing the data to be written - \param pos file position to which to be written - \param len the number of bytes to be written - \return the number of bytes actually written or an error code -*/ -ssize_t -BPrivate::Storage::write(BPrivate::Storage::FileDescriptor fd, const void *buf, off_t pos, - size_t len) -{ - ssize_t result = (buf == NULL || pos < 0 ? B_BAD_VALUE : B_OK); - if (result == B_OK) { - result = ::write_pos(fd, pos, buf, len); - if (result == -1) - result = errno; - } - return result; -} - -/*! \param fd the file descriptor - \param pos the relative new position of the read/write pointer in bytes - \param mode \c SEEK_SET/\c SEEK_END/\c SEEK_CUR to indicate that \a pos - is relative to the file's beginning/end/current read/write pointer - \return the new position of the read/write pointer relative to the - beginning of the file, or an error code -*/ -off_t -BPrivate::Storage::seek(BPrivate::Storage::FileDescriptor fd, off_t pos, - BPrivate::Storage::SeekMode mode) -{ - off_t result = ::lseek(fd, pos, mode); - if (result == -1) - result = errno; - return result; -} - -/*! \param fd the file descriptor - \return the position of the read/write pointer relative to the - beginning of the file, or an error code -*/ -off_t -BPrivate::Storage::get_position(BPrivate::Storage::FileDescriptor fd) -{ - off_t result = ::lseek(fd, 0, SEEK_CUR); - if (result == -1) - result = errno; - return result; -} - -BPrivate::Storage::FileDescriptor -BPrivate::Storage::dup(BPrivate::Storage::FileDescriptor file) -{ - return ::dup(file); -} - -/*! If the supplied file descriptor is -1, the copy will be -1 as well and - B_OK is returned. - \param file the file descriptor to be duplicated - \param result the variable the resulting file descriptor will be stored in - \return B_OK, if everything went fine, or an error code. -*/ -status_t -BPrivate::Storage::dup( FileDescriptor file, FileDescriptor& result ) -{ - status_t error = B_OK; - if (file == -1) - result = -1; - else { - result = dup(file); - if (result == -1) - error = errno; - } - return error; -} - -status_t -BPrivate::Storage::sync( FileDescriptor file ) -{ - return (fsync(file) == -1) ? errno : B_OK ; -} - -//! /todo Get rid of DumpLock() at some point (it's only for debugging) -void DumpLock(BPrivate::Storage::FileLock &lock) -{ - cout << endl; - cout << "type == "; - switch (lock.l_type) { - case F_RDLCK: - cout << "F_RDLCK"; - break; - - case F_WRLCK: - cout << "F_WRLCK"; - break; - - case F_UNLCK: - cout << "F_UNLCK"; - break; - - default: - cout << lock.l_type; - break; - } - cout << endl; - - cout << "whence == " << lock.l_whence << endl; - cout << "start == " << lock.l_start << endl; - cout << "len == " << lock.l_len << endl; - cout << "pid == " << lock.l_pid << endl; - cout << endl; -} - -// As best I can tell, fcntl(fd, F_SETLK, lock) and fcntl(fd, F_GETLK, lock) -// are unimplemented in BeOS R5. Thus locking we'll have to wait for the new -// kernel. I believe this function would work if fcntl() worked correctly. -status_t -BPrivate::Storage::lock(FileDescriptor file, OpenFlags mode, FileLock *lock) -{ - return B_FILE_ERROR; -/* - if (lock == NULL) - return B_BAD_VALUE; - -// DumpLock(*lock); - short lock_type; - switch (mode) { - case READ: - lock_type = F_RDLCK; - break; - - case WRITE: - case READ_WRITE: - default: - lock_type = F_WRLCK; - break; - } - -// lock->l_type = F_UNLCK; - lock->l_type = lock_type; - lock->l_whence = SEEK_SET; - lock->l_start = 0; // Beginning of file... - lock->l_len = 0; // ...to end of file - lock->l_pid = 0; // Don't really care :-) - -// DumpLock(*lock); - ::fcntl(file, F_GETLK, lock); -// DumpLock(*lock); - if (lock->l_type != F_UNLCK) { - return errno; - } - -// lock->l_type = F_RDLCK; - lock->l_type = lock_type; -// DumpLock(*lock); - - errno = 0; - - return (::fcntl(file, F_SETLK, lock) == 0) ? B_OK : errno; -*/ -} - -// As best I can tell, fcntl(fd, F_SETLK, lock) and fcntl(fd, F_GETLK, lock) -// are unimplemented in BeOS R5. Thus locking will have to wait for the new -// kernel. I believe this function would work if fcntl() worked correctly. -status_t -BPrivate::Storage::unlock(FileDescriptor file, FileLock *lock) -{ - return B_FILE_ERROR; - -/* - if (lock == NULL) - return B_BAD_VALUE; - - lock->l_type = F_UNLCK; - - return (::fcntl(file, F_SETLK, lock) == 0) ? B_OK : errno ; -*/ -} - -status_t -BPrivate::Storage::get_stat(const char *path, Stat *s) -{ - if (path == NULL || s == NULL) - return B_BAD_VALUE; - - return (::lstat(path, s) == -1) ? errno : B_OK ; -} - -status_t -BPrivate::Storage::get_stat(FileDescriptor file, Stat *s) -{ - if (s == NULL) - return B_BAD_VALUE; - - return (::fstat(file, s) == -1) ? errno : B_OK ; -} - -status_t -BPrivate::Storage::get_stat(entry_ref &ref, Stat *result) -{ - char path[B_PATH_NAME_LENGTH]; - status_t status; - - status = BPrivate::Storage::entry_ref_to_path(&ref, path, B_PATH_NAME_LENGTH); - return (status != B_OK) ? status : BPrivate::Storage::get_stat(path, result); -} - -status_t -BPrivate::Storage::set_stat(FileDescriptor file, Stat &s, StatMember what) -{ - int result; - - switch (what) { - case FS_WRITE_STAT_MODE: - // For some stupid reason, BeOS R5 has no fchmod function, just - // chmod(char *filename, ...), so for the moment we're screwed. -// result = fchmod(file, s.st_mode); -// break; - return B_BAD_VALUE; - - case FS_WRITE_STAT_UID: - result = ::fchown(file, s.st_uid, 0xFFFFFFFF); - break; - - case FS_WRITE_STAT_GID: - { - // Should work, but doesn't. uid is set to 0xffffffff. -// result = ::fchown(file, 0xFFFFFFFF, s.st_gid); - Stat st; - result = fstat(file, &st); - if (result == 0) - result = ::fchown(file, st.st_uid, s.st_gid); - break; - } - - case FS_WRITE_STAT_SIZE: - // For enlarging files the truncate() behavior seems to be not - // precisely defined, but with a bit of luck it might come pretty - // close to what we need. - result = ::ftruncate(file, s.st_size); - break; - - // These would all require a call to utime(char *filename, ...), but - // we have no filename, only a file descriptor, so they'll have to - // wait until our new kernel shows up (or we decide to try calling - // into the R5 kernel ;-) - case FS_WRITE_STAT_ATIME: - case FS_WRITE_STAT_MTIME: - case FS_WRITE_STAT_CRTIME: - // ToDo: implement us! - return B_BAD_VALUE; - - default: - return B_BAD_VALUE; - } - - return (result == -1) ? errno : B_OK ; -} - -status_t -BPrivate::Storage::set_stat(const char *file, Stat &s, StatMember what) -{ - int result; - - //! \todo Test/verify set_stat() functionality - switch (what) { - case FS_WRITE_STAT_MODE: - result = ::chmod(file, s.st_mode); - break; - - case FS_WRITE_STAT_UID: - { - // Doesn't work: chown seems to traverse links. -// result = ::chown(file, s.st_uid, 0xFFFFFFFF); - int fd = ::open(file, O_RDWR | O_NOTRAVERSE); - if (fd != -1) { - status_t error = set_stat(fd, s, what); - ::close(fd); - return error; - } else - result = -1; - break; - } - case FS_WRITE_STAT_GID: - { - // Doesn't work: chown seems to traverse links. -// result = ::chown(file, 0xFFFFFFFF, s.st_gid); - int fd = ::open(file, O_RDWR | O_NOTRAVERSE); - if (fd != -1) { - status_t error = set_stat(fd, s, what); - ::close(fd); - return error; - } else - result = -1; - break; - } - - case FS_WRITE_STAT_SIZE: - // For enlarging files the truncate() behavior seems to be not - // precisely defined, but with a bit of luck it might come pretty - // close to what we need. - result = ::truncate(file, s.st_size); - break; - - case FS_WRITE_STAT_ATIME: - case FS_WRITE_STAT_MTIME: - { - // Grab the previous mod and access times so we only overwrite - // the specified time and not both - Stat oldStat; - result = ::stat(file, &oldStat); - if (result < 0) - break; - - utimbuf buffer; - buffer.actime = (what == FS_WRITE_STAT_ATIME) ? s.st_atime : oldStat.st_atime; - buffer.modtime = (what == FS_WRITE_STAT_MTIME) ? s.st_mtime : oldStat.st_mtime; - result = ::utime(file, &buffer); - break; - } - - //! \todo Implement set_stat(..., WSTAT_CRTIME) - case FS_WRITE_STAT_CRTIME: - return B_BAD_VALUE; - - default: - return B_BAD_VALUE; - } - - return (result == -1) ? errno : B_OK; -} - - - -//------------------------------------------------------------------------------ -// Attribute Functions -//------------------------------------------------------------------------------ - -ssize_t -BPrivate::Storage::read_attr ( BPrivate::Storage::FileDescriptor file, const char *attribute, - uint32 type, off_t pos, void *buf, size_t count ) -{ - if (attribute == NULL || buf == NULL) - return B_BAD_VALUE; - - ssize_t result = fs_read_attr ( file, attribute, type, pos, buf, count ); - return (result == -1 ? errno : result); -} - -ssize_t -BPrivate::Storage::write_attr ( BPrivate::Storage::FileDescriptor file, - const char *attribute, uint32 type, off_t pos, - const void *buf, size_t count ) -{ - if (attribute == NULL || buf == NULL) - return B_BAD_VALUE; - - ssize_t result = fs_write_attr ( file, attribute, type, pos, buf, count ); - return (result == -1 ? errno : result); -} - -status_t -BPrivate::Storage::rename_attr(FileDescriptor file, const char *oldName, - const char *newName) -{ - status_t error = (oldName && newName ? B_OK : B_BAD_VALUE); - // Figure out how much data there is - attr_info info; - if (error == B_OK) { - error = stat_attr(file, oldName, &info); - if (error != B_OK) - error = B_BAD_VALUE; // This is what R5::BNode returns... - } - // Alloc a buffer - char *data = NULL; - if (error == B_OK) { - // alloc at least one byte - data = new(nothrow) char[max(info.size, (off_t)1LL)]; - if (data == NULL) - error = B_NO_MEMORY; - } - // Read in the data - if (error == B_OK) { - ssize_t size = read_attr(file, oldName, info.type, 0, data, info.size); - if (size != info.size) { - if (size < 0) - error = size; - else - error = B_ERROR; - } - } - // Write it to the new attribute - if (error == B_OK) { - ssize_t size = 0; - if (info.size > 0) - size = write_attr(file, newName, info.type, 0, data, info.size); - if (size != info.size) { - if (size < 0) - error = size; - else - error = B_ERROR; - } - } - // free the buffer - if (data) - delete[] data; - // Remove the old attribute - if (error == B_OK) - error = remove_attr(file, oldName); - return error; -} - -status_t -BPrivate::Storage::remove_attr ( BPrivate::Storage::FileDescriptor file, const char *attr ) -{ - if (attr == NULL) - return B_BAD_VALUE; - - // fs_remove_attr is supposed to set errno properly upon failure, - // but currently does not appear to. It isn't set consistent - // with what is returned by R5::BNode::RemoveAttr(), and it isn't - // set consistent with what the BeBook's claims it is set to either. - return fs_remove_attr ( file, attr ) == -1 ? errno : B_OK ; -} - -status_t -BPrivate::Storage::stat_attr( FileDescriptor file, const char *name, AttrInfo *ai ) -{ - if (name == NULL || ai == NULL) - return B_BAD_VALUE; - - return (fs_stat_attr( file, name, ai ) == -1) ? errno : B_OK ; -} - - -//------------------------------------------------------------------------------ -// Attribute Directory Functions -//------------------------------------------------------------------------------ - -status_t -BPrivate::Storage::open_attr_dir( FileDescriptor file, FileDescriptor &result ) -{ - result = NullFd; - if (DIR *dir = ::fs_fopen_attr_dir(file)) { - result = dir->fd; - free(dir); - } - return (result < 0) ? errno : B_OK ; -} - -status_t -BPrivate::Storage::rewind_attr_dir( FileDescriptor dir ) -{ - if (dir < 0) - return B_BAD_VALUE; - else { - // init a DIR structure - LongDIR dirDir; - dirDir.fd = dir; - ::fs_rewind_attr_dir(&dirDir); - return B_OK; - } -} - -// buffer must be large enough!!! -status_t -BPrivate::Storage::read_attr_dir( FileDescriptor dir, BPrivate::Storage::DirEntry& buffer ) -{ - // init a DIR structure - LongDIR dirDir; - dirDir.fd = dir; - // check parameters - status_t error = B_OK; - // read one entry and copy it into the buffer - if (dirent *entry = ::fs_read_attr_dir(&dirDir)) { - // Don't trust entry->d_reclen. - // Unlike stated in BeBook::BEntryList, the value is not the length - // of the whole structure, but only of the name. Some FSs count - // the terminating '\0', others don't. - // So we calculate the size ourselves (including the '\0'): - size_t entryLen = entry->d_name + strlen(entry->d_name) + 1 - - (char*)entry; - memcpy(&buffer, entry, entryLen); - } else - error = B_ENTRY_NOT_FOUND; - return error; -} - -status_t -BPrivate::Storage::close_attr_dir ( FileDescriptor dir ) -{ - if (dir == BPrivate::Storage::NullFd) - return B_BAD_VALUE; - - // init a DIR structure - if (LongDIR* dirDir = (LongDIR*)malloc(sizeof(LongDIR))) { - dirDir->fd = dir; - return (fs_close_attr_dir(dirDir) == -1) ? errno : B_OK ; - } - return B_NO_MEMORY; -} - - -//------------------------------------------------------------------------------ -// Directory Functions -//------------------------------------------------------------------------------ - -status_t -BPrivate::Storage::open_dir( const char *path, FileDescriptor &result ) -{ - result = NullFd; - if (DIR *dir = ::opendir(path)) { - result = dir->fd; - free(dir); - } - return (result < 0) ? errno : B_OK ; -} - -/*! The parent directory must already exist. - \param path the directory's path name - \param mode the file permissions - \return B_OK, if everything went fine, an error code otherwise -*/ -status_t -BPrivate::Storage::create_dir( const char *path, mode_t mode ) -{ - status_t error = (path ? B_OK : B_BAD_VALUE); - if (error == B_OK) { - if (mkdir(path, mode) == -1) - error = errno; - } - return error; -} - -/*! The parent directory must already exist. - \param path the directory's path name - \param result set to a file descriptor for the new directory - \param mode the file permissions - \return B_OK, if everything went fine, an error code otherwise -*/ -status_t -BPrivate::Storage::create_dir( const char *path, FileDescriptor &result, - mode_t mode ) -{ - status_t error = create_dir(path, mode); - if (error == B_OK) - error = open_dir(path, result); - return error; -} - -/*! \param dir the directory - \param buffer the dirent structure to be filled - \param length the size of the dirent structure - \param count the maximal number of entries to be read - \return - - the number of entries stored in the supplied buffer, - - \c 0, if at the end of the entry list, - - \c B_BAD_VALUE, if \a buffer is NULL, or the supplied buffer is too small -*/ -int32 -BPrivate::Storage::read_dir( FileDescriptor dir, DirEntry *buffer, size_t length, - int32 count ) -{ - // init a DIR structure - LongDIR dirDir; - dirDir.fd = dir; - // check parameters - int32 result = (buffer == NULL ? B_BAD_VALUE : 0); - if (result == 0 && count > 0) { - // read one entry and copy it into the buffer - if (dirent *entry = readdir(&dirDir)) { - // Don't trust entry->d_reclen. - // Unlike stated in BeBook::BEntryList, the value is not the length - // of the whole structure, but only of the name. Some FSs count - // the terminating '\0', others don't. - // So we calculate the size ourselves (including the '\0'): - size_t entryLen = entry->d_name + strlen(entry->d_name) + 1 - - (char*)entry; - if (length >= entryLen) { - memcpy(buffer, entry, entryLen); - result = 1; - } else // buffer too small - result = B_BAD_VALUE; - } - } - return result; -} - -status_t -BPrivate::Storage::rewind_dir( FileDescriptor dir ) -{ - if (dir < 0) - return B_BAD_VALUE; - else { - // init a DIR structure - LongDIR dirDir; - dirDir.fd = dir; - ::rewinddir(&dirDir); - return B_OK; - } -} - -status_t -BPrivate::Storage::find_dir( FileDescriptor dir, const char *name, - DirEntry *result, size_t length ) -{ - if (dir < 0 || name == NULL || result == NULL) - return B_BAD_VALUE; - - status_t status; - - status = BPrivate::Storage::rewind_dir(dir); - if (status == B_OK) { - while ( BPrivate::Storage::read_dir(dir, result, length, 1) == 1) - { - if (strcmp(result->d_name, name) == 0) - return B_OK; - } - status = B_ENTRY_NOT_FOUND; - } - - return status; -} - -status_t -BPrivate::Storage::find_dir( FileDescriptor dir, const char *name, entry_ref *result ) -{ - status_t status = (result ? B_OK : B_BAD_VALUE); - LongDirEntry entry; - if (status == B_OK) - status = BPrivate::Storage::find_dir(dir, name, &entry, sizeof(entry)); - if (status == B_OK) { - result->device = entry.d_pdev; - result->directory = entry.d_pino; - status = result->set_name(entry.d_name); - } - return status; -} - -status_t -BPrivate::Storage::dup_dir( FileDescriptor dir, FileDescriptor &result ) -{ - return BPrivate::Storage::dup(dir, result); -} - -status_t -BPrivate::Storage::close_dir( FileDescriptor dir ) -{ - // init a DIR structure - if (LongDIR* dirDir = (LongDIR*)malloc(sizeof(LongDIR))) { - dirDir->fd = dir; - return (::closedir(dirDir) == -1) ? errno : B_OK; - } - return B_NO_MEMORY; -} - -//------------------------------------------------------------------------------ -// SymLink functions -//------------------------------------------------------------------------------ - -/*! The parent directory must already exist. - \param path the link's path name - \param linkToPath the path name the link shall point to - \return B_OK, if everything went fine, an error code otherwise -*/ -status_t -BPrivate::Storage::create_link( const char *path, const char *linkToPath ) -{ - status_t error = (path && linkToPath ? B_OK : B_BAD_VALUE); - if (error == B_OK) { - if (symlink(linkToPath, path) == -1) - error = errno; - } - return error; -} - -/*! The parent directory must already exist. - \param path the link's path name - \param linkToPath the path name the link shall point to - \param result set to a file descriptor for the new symbolic link - \return B_OK, if everything went fine, an error code otherwise -*/ -status_t -BPrivate::Storage::create_link( const char *path, const char *linkToPath, - FileDescriptor &result) -{ - status_t error = create_link(path, linkToPath); - if (error == B_OK) - error = open(path, O_RDWR, result); - return error; -} - -ssize_t -BPrivate::Storage::read_link( const char *path, char *result, size_t size ) -{ - if (result == NULL) - return B_BAD_VALUE; - // Don't null terminate, when the buffer is too small. That would make - // things more difficult. BTW: readlink() returns the actual length of - // the link contents and so do we. - int len = ::readlink(path, result, size); - if (len == -1) { - if (size > 0) - result[0] = 0; // Null terminate - return errno; - } else { - if (len < (int)size) - result[len] = 0; // Null terminate - return len; - } -} - -ssize_t -BPrivate::Storage::read_link( FileDescriptor fd, char *result, size_t size ) -{ - ssize_t error = (result ? B_OK : B_BAD_VALUE); - // no way to implement it :-( - if (error == B_OK) - error = B_ERROR; - return error; -} - - -//------------------------------------------------------------------------------ -// Query Functions -//------------------------------------------------------------------------------ - -status_t -BPrivate::Storage::open_query( dev_t device, const char *query, uint32 flags, - FileDescriptor &result ) -{ - if (flags & B_LIVE_QUERY) - return B_BAD_VALUE; - result = NullFd; - if (DIR *dir = fs_open_query(device, query, flags)) { - result = dir->fd; - free(dir); - } - return (result < 0) ? errno : B_OK ; -} - -status_t -BPrivate::Storage::open_live_query( dev_t device, const char *query, uint32 flags, - port_id port, int32 token, - FileDescriptor &result ) -{ - if (!(flags & B_LIVE_QUERY)) - return B_BAD_VALUE; - result = NullFd; - if (DIR *dir = fs_open_live_query(device, query, flags, port, token)) { - result = dir->fd; - free(dir); - } - return (result < 0) ? errno : B_OK ; -} - -/*! \param query the query - \param buffer the dirent structure to be filled - \param length the size of the dirent structure - \param count the maximal number of entries to be read - \return - - the number of entries stored in the supplied buffer, - - \c 0, if at the end of the entry list, - - \c B_BAD_VALUE, if \a buffer is NULL, or the supplied buffer is too small -*/ -int32 -BPrivate::Storage::read_query( FileDescriptor query, DirEntry *buffer, size_t length, - int32 count ) -{ - // init a DIR structure - LongDIR queryDir; - queryDir.fd = query; - // check parameters - int32 result = (buffer == NULL ? B_BAD_VALUE : 0); - if (result == 0 && count > 0) { - // read one entry and copy it into the buffer - if (dirent *entry = fs_read_query(&queryDir)) { - // Don't trust entry->d_reclen. - // Unlike stated in BeBook::BEntryList, the value is not the length - // of the whole structure, but only of the name. Some FSs count - // the terminating '\0', others don't. - // So we calculate the size ourselves (including the '\0'): - size_t entryLen = entry->d_name + strlen(entry->d_name) + 1 - - (char*)entry; - if (length >= entryLen) { - memcpy(buffer, entry, entryLen); - result = 1; - } else // buffer too small - result = B_BAD_VALUE; - } - } - return result; -} - -status_t -BPrivate::Storage::close_query( FileDescriptor query ) -{ - // init a DIR structure - if (LongDIR* queryDir = (LongDIR*)malloc(sizeof(LongDIR))) { - queryDir->fd = query; - return (fs_close_query(queryDir) == -1) ? errno : B_OK; - } - return B_NO_MEMORY; -} - - -//------------------------------------------------------------------------------ -// Miscellaneous Functions -//------------------------------------------------------------------------------ - -status_t -BPrivate::Storage::entry_ref_to_path( const struct entry_ref *ref, char *result, - size_t size ) -{ - if (ref == NULL) { - return B_BAD_VALUE; - } else { - return entry_ref_to_path(ref->device, ref->directory, ref->name, - result, size); - } -} - - -status_t -BPrivate::Storage::entry_ref_to_path(dev_t device, ino_t directory, - const char *name, char *path, size_t size) -{ - status_t error; - if (strcmp(name, ".") == 0) { - error = _kern_dir_node_ref_to_path(device, directory, path, size); - } else if (strcmp(name, "..") == 0) { - char tmpPath[B_PATH_NAME_LENGTH]; - error = _kern_dir_node_ref_to_path(device, directory, tmpPath, - B_PATH_NAME_LENGTH); - if (error != B_OK) - return error; - strlcat(tmpPath, "/", B_PATH_NAME_LENGTH); - strlcat(tmpPath, name, B_PATH_NAME_LENGTH); - error = get_canonical_path(tmpPath, path, size); - } else { - error = _kern_dir_node_ref_to_path(device, directory, path, size); - if (error != B_OK) - return error; - int32 len = strlen(path); - if (path[len - 1] != '/') - strlcat(path, "/", B_PATH_NAME_LENGTH); - strlcat(path, name, B_PATH_NAME_LENGTH); - } - return error; -} - - -status_t -BPrivate::Storage::dir_to_self_entry_ref( FileDescriptor dir, entry_ref *result ) -{ - if (dir == BPrivate::Storage::NullFd || result == NULL) - return B_BAD_VALUE; - return find_dir(dir, ".", result); -} - -status_t -BPrivate::Storage::dir_to_path( FileDescriptor dir, char *result, size_t size ) -{ - if (dir < 0 || result == NULL) - return B_BAD_VALUE; - // get stat - Stat st; - status_t error = get_stat(dir, &st); - if (error != B_OK) - return error; - // get path for the node ref - return _kern_dir_node_ref_to_path(st.st_dev, st.st_ino, result, size); -} - -/*! \param path the path name. - \param result a pointer to a buffer the resulting path name shall be - written into. - \param size the size of the buffer - \return \c B_OK if everything went fine, an error code otherwise -*/ -status_t -BPrivate::Storage::get_canonical_path(const char *path, char *result, size_t size) -{ - status_t error = (path && result ? B_OK : B_BAD_VALUE); - if (error == B_OK) { - char *dirPath = NULL; - char *leafName = NULL; - error = split_path(path, dirPath, leafName); - if (error == B_OK) { - // handle special leaf names ("." and "..") - if (strcmp(leafName, ".") == 0 || strcmp(leafName, "..") == 0) - error = get_canonical_dir_path(path, result, size); - else { - // get the canonical dir path and append the leaf name - error = get_canonical_dir_path(dirPath, result, size); - if (error == B_OK) { - size_t dirPathLen = strlen(result); - // "/" doesn't need a '/' to be appended - bool separatorNeeded = (result[dirPathLen - 1] != '/'); - size_t neededSize = dirPathLen + (separatorNeeded ? 1 : 0) - + strlen(leafName) + 1; - if (neededSize <= size) { - if (separatorNeeded) - strcat(result + dirPathLen, "/"); - strcat(result + dirPathLen, leafName); - } else - error = B_BAD_VALUE; - } - } - delete[] dirPath; - delete[] leafName; - } - } - return error; -} - -/*! The caller is responsible for deleting the returned path name. - \param path the path name. - \param result in this variable the resulting path name is returned - \return \c B_OK if everything went fine, an error code otherwise -*/ -status_t -BPrivate::Storage::get_canonical_path(const char *path, char *&result) -{ - status_t error = (path ? B_OK : B_BAD_VALUE); - if (error == B_OK) { - result = new(nothrow) char[B_PATH_NAME_LENGTH]; - if (!result) - error = B_NO_MEMORY; - if (error == B_OK) { - error = get_canonical_path(path, result, B_PATH_NAME_LENGTH); - if (error != B_OK) { - delete[] result; - result = NULL; - } - } - } - return error; -} - -/*! \param path the path name. - \param result a pointer to a buffer the resulting path name shall be - written into. - \param size the size of the buffer - \return \c B_OK if everything went fine, an error code otherwise -*/ -status_t -BPrivate::Storage::get_canonical_dir_path(const char *path, char *result, size_t size) -{ - status_t error = (path && result ? B_OK : B_BAD_VALUE); - if (error == B_OK) { - FileDescriptor dir; - error = open_dir(path, dir); - if (error == B_OK) { - error = dir_to_path(dir, result, size); - close_dir(dir); - } - } - return error; -} - -/*! The caller is responsible for deleting the returned path name. - \param path the path name. - \param result in this variable the resulting path name is returned - \return \c B_OK if everything went fine, an error code otherwise -*/ -status_t -BPrivate::Storage::get_canonical_dir_path(const char *path, char *&result) -{ - status_t error = (path ? B_OK : B_BAD_VALUE); - if (error == B_OK) { - result = new(nothrow) char[B_PATH_NAME_LENGTH]; - if (!result) - error = B_NO_MEMORY; - if (error == B_OK) { - error = get_canonical_dir_path(path, result, B_PATH_NAME_LENGTH); - if (error != B_OK) { - delete[] result; - result = NULL; - } - } - } - return error; -} - -status_t -BPrivate::Storage::get_app_path(char *buffer) -{ - status_t error = (buffer ? B_OK : B_BAD_VALUE); - image_info info; - int32 cookie = 0; - bool found = false; - if (error == B_OK) { - while (!found && get_next_image_info(0, &cookie, &info) == B_OK) { - if (info.type == B_APP_IMAGE) { - strncpy(buffer, info.name, B_PATH_NAME_LENGTH); - buffer[B_PATH_NAME_LENGTH] = 0; - found = true; - } - } - } - if (error == B_OK && !found) - error = B_ENTRY_NOT_FOUND; - return error; -} - -bool -BPrivate::Storage::entry_ref_is_root_dir( const entry_ref *ref ) -{ - return ref && ref->directory == 1 && ref->device == 1 && ref->name[0] == '.' - && ref->name[1] == 0; -} - -bool -BPrivate::Storage::device_is_root_device(dev_t device) { - return device == 1; -} - -status_t -BPrivate::Storage::rename(const char *oldPath, const char *newPath) -{ - if (oldPath == NULL || newPath == NULL) - return B_BAD_VALUE; - - return (::rename(oldPath, newPath) == -1) ? errno : B_OK ; -} - -/*! Removes path from the filesystem. */ -status_t -BPrivate::Storage::remove(const char *path) -{ - if (path == NULL) - return B_BAD_VALUE; - - return (::remove(path) == -1) ? errno : B_OK ; -} - - -/*! - \param device The device ID of the volume in question. - \param name The volume's new name. Must not be longer than - \c B_FILE_NAME_LENGTH (including the terminating null). - \return - - \c B_OK: Everything went fine. - - \c B_BAD_VALUE: \c NULL \a name. - - \c B_NAME_TOO_LONG: \a name is longer than \c B_FILE_NAME_LENGTH. - - another error code -*/ - -status_t -BPrivate::Storage::set_volume_name(dev_t device, const char *name) -{ - // check parameter and initialization - status_t error = (name ? B_OK : B_BAD_VALUE); - if (error == B_OK && strlen(name) >= B_FILE_NAME_LENGTH) - error = B_NAME_TOO_LONG; - - // replace the name and let it be written - if (error == B_OK) { - fs_info info; - strlcpy(info.volume_name, name, sizeof(info.volume_name)); - error = _kern_write_fs_info(device, &info, FS_WRITE_FSINFO_NAME); - } - return error; -} -