blob: eaed4247f20e8dd8836c4c568c805388461d3c8e [file] [log] [blame]
/*
* contributeur : Sachin Bhamare sbhamare@panasas.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* ---------------------------------------
*/
/**
* @file os/linux/subr.c
* @author Sachin Bhamare <sbhamare@panasas.com>
* @brief Platform dependant subroutines for Linux
*
*/
#include "fsal.h"
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <sys/fsuid.h>
#include <sys/syscall.h>
#include "os/subr.h"
/**
* @brief Read system directory entries into the buffer
*
* @param[in] fd File descriptor of open directory
* @param[in] buf The buffer
* @param[in] bcount Buffer size
* @param[in,out] basepp Offset into "file" after this read
*/
int vfs_readents(int fd, char *buf, unsigned int bcount, off_t *basepp)
{
int retval = 0;
retval = syscall(SYS_getdents64, fd, buf, bcount);
if (retval >= 0)
*basepp += retval;
return retval;
}
/**
* @brief Mash a FreeBSD directory entry into the generic form
*
* @param buf [in] pointer into buffer read by vfs_readents
* @param bpos [in] byte offset into buf to decode
* @param vd [in] pointer to the generic struct
* @param base [in] base file offset for this buffer - not used
*
* @return true. Linux entries are never empty.
*/
bool to_vfs_dirent(char *buf, int bpos, struct vfs_dirent *vd, off_t base)
{
struct dirent64 *dp = (struct dirent64 *)(buf + bpos);
char type;
vd->vd_ino = dp->d_ino;
vd->vd_reclen = dp->d_reclen;
type = buf[dp->d_reclen - 1];
vd->vd_type = type;
vd->vd_offset = dp->d_off;
vd->vd_name = dp->d_name;
return true;
}
/**
* @brief Platform specific wrapper for utimensat().
*
* @param[in] fd File descriptor
* @param[in] path Name of a file
* @param[in] ts Array of struct timespec
* @param[in] flags Flags
*
* @return 0 on success, -1 on error (errno set to indicate the error).
*/
int vfs_utimesat(int fd, const char *path, const struct timespec ts[2],
int flags)
{
return utimensat(fd, path, ts, flags);
}
/**
* @brief Platform specific wrapper fro futimens().
*
* @param[in] fd File descriptor
* @param[in] ts Array of struct timespec
*
* @return 0 on success, -1 on error (errno set to indicate the error).
*/
int vfs_utimes(int fd, const struct timespec *ts)
{
return futimens(fd, ts);
}
uid_t setuser(uid_t uid)
{
uid_t orig_uid = setfsuid(uid);
if (uid != setfsuid(uid))
LogCrit(COMPONENT_FSAL, "Could not set user identity");
return orig_uid;
}
gid_t setgroup(gid_t gid)
{
gid_t orig_gid = setfsgid(gid);
if (gid != setfsgid(gid))
LogCrit(COMPONENT_FSAL, "Could not set group identity");
return orig_gid;
}
int set_threadgroups(size_t size, const gid_t *list)
{
return syscall(__NR_setgroups, size, list);
}