/*---------------------------------------------------------------------------*/
/*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 <unlimitedscolobb@gmail.com>.
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 <sys/mman.h>
#include <fcntl.h>
#include <hurd/fshelp.h>
/*---------------------------------------------------------------------------*/
#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 */
/*---------------------------------------------------------------------------*/