/*---------------------------------------------------------------------------*/ /*lib.c*/ /*---------------------------------------------------------------------------*/ /*Basic routines for filesystem manipulations*/ /*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ /*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008, 2009 Free Software Foundation, Inc. Written by Sergiu Ivanov . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ #define _GNU_SOURCE 1 /*---------------------------------------------------------------------------*/ #include #include #include /*---------------------------------------------------------------------------*/ #include "lib.h" #include "debug.h" /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*--------Functions----------------------------------------------------------*/ /*Fetches directory entries for `dir`*/ error_t dir_entries_get (file_t dir, char **dirent_data, /*the list of directory entries as returned by dir_readdir */ size_t * dirent_data_size,/*the size of `dirent_data` */ struct dirent ***dirent_list/*the array of pointers to beginnings of dirents in dirent_data */ ) { error_t err = 0; /*The data (array of dirents(?)) returned by dir_readdir */ char *data; /*The size of `data` */ size_t data_size; /*The number of entries in `data` */ int entries_num; /*Try to read the contents of the specified directory */ err = dir_readdir (dir, &data, &data_size, 0, -1, 0, &entries_num); if (err) return err; /*Create a new list of dirents */ struct dirent **list; /*Allocate the memory for the list of dirents and for the finalizing element */ list = malloc (sizeof (struct dirent *) * (entries_num + 1)); /*If memory allocation has failed */ if (!list) { /*free the result of dir_readdir */ munmap (data, data_size); /*return the corresponding error */ return ENOMEM; } /*The current directory entry */ struct dirent *dp; int i; /*Go through every element of the list of dirents */ for (i = 0, dp = (struct dirent *) data; i < entries_num; ++i, dp = (struct dirent *) ((char *) dp + dp->d_reclen)) /*copy the current value into the list */ *(list + i) = dp; /*Nullify the last element of the list */ *(list + i) = NULL; /*Copy the required values in the parameters */ *dirent_data = data; *dirent_data_size = data_size; *dirent_list = list; /*Return success */ return err; } /*dir_entries_get */ /*---------------------------------------------------------------------------*/ /*Lookup `name` under `dir` (or cwd, if `dir` is invalid)*/ error_t file_lookup (file_t dir, char *name, int flags0, /*try to open with these flags first */ int flags1, /*try to open with these flags, if `flags0` fail */ int mode, /*if the file is to be created, create it with this mode */ file_t * port, /*store the port to the looked up file here */ io_statbuf_t * stat /*store the stat information here */ ) { error_t err = 0; /*The port to the looked up file */ file_t p; /*The stat information about the looked up file */ io_statbuf_t s; /*Performs a lookup under 'dir' or in cwd, if `dir` is invalid */ file_t do_file_lookup (file_t dir, char *name, /*lookup this file */ int flags, /*lookup the file with these flags */ int mode /*if a new file is to be created, create it with this mode */ ) { /*The result of lookup */ file_t p; /*If `dir` is a valid port */ if (dir != MACH_PORT_NULL) /*try to lookup `name` under `dir` */ p = file_name_lookup_under (dir, name, flags, mode); else /*lookup `name` under current cwd */ p = file_name_lookup (name, flags, mode); /*Return the result of the lookup */ return p; } /*do_file_lookup */ /*Lookup `name` under the suggested `dir` */ p = do_file_lookup (dir, name, flags0, mode); /*If the lookup failed */ if (p == MACH_PORT_NULL) /*try to lookup for `name` using alternative flags `flags1` */ p = do_file_lookup (dir, name, flags1, mode); /*If the port is valid */ if (p != MACH_PORT_NULL) { /*If stat information is required */ if (stat) { /*obtain stat information for `p` */ err = io_stat (p, &s); if (err) PORT_DEALLOC (p); } } else /*copy `errno` into `err` */ err = errno; /*If no errors have happened during lookup */ if (!err) { /*copy the resulting port into *`port` */ *port = p; /*fill in the receiver for stat information, if requried */ if (stat) *stat = s; } /*Return the result of performing operations */ return err; } /*file_lookup */ /*---------------------------------------------------------------------------*/ /*Checks whether `user` has the right to open the node described by `stat` with `flags`*/ error_t check_open_permissions (struct iouser * user, io_statbuf_t * stat, int flags) { error_t err = 0; /*Cheks user's permissions */ if (flags & O_READ) err = fshelp_access (stat, S_IREAD, user); if (!err && (flags & O_WRITE)) err = fshelp_access (stat, S_IWRITE, user); if (!err && (flags & O_EXEC)) err = fshelp_access (stat, S_IEXEC, user); /*Return the result of the check */ return err; } /*check_open_permissions */ /*---------------------------------------------------------------------------*/