/* Editor Settings: expandtabs and use 4 spaces for indentation
* ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: *
* -*- mode: c, c-basic-offset: 4 -*- */
/*
* Copyright Likewise Software
* All rights reserved.
*
* 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, see
* .
*
* LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
* TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
* WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
* TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
* GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU
* HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
* TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
* license@likewisesoftware.com
*/
/*
* Copyright (C) Likewise Software. All rights reserved.
*
* Module Name:
*
* syswrap.c
*
* Abstract:
*
* Likewise Posix File System Driver (PVFS)
*
* Syscall wrapper functions
*
* Authors: Gerald Carter
*/
#include "pvfs.h"
/**********************************************************
*********************************************************/
static NTSTATUS
CopyUnixStatToPvfsStat(
PPVFS_STAT pPvfsStat,
struct stat *pSbuf
)
{
NTSTATUS ntError = STATUS_SUCCESS;
pPvfsStat->s_mode = pSbuf->st_mode;
pPvfsStat->s_ino = pSbuf->st_ino;
pPvfsStat->s_dev = pSbuf->st_dev;
pPvfsStat->s_rdev = pSbuf->st_rdev;
pPvfsStat->s_nlink = pSbuf->st_nlink;
pPvfsStat->s_uid = pSbuf->st_uid;
pPvfsStat->s_gid = pSbuf->st_gid;
pPvfsStat->s_size = pSbuf->st_size;
pPvfsStat->s_alloc = pSbuf->st_blocks * 512;
pPvfsStat->s_atime = pSbuf->st_atime;
pPvfsStat->s_ctime = pSbuf->st_ctime;
pPvfsStat->s_mtime = pSbuf->st_mtime;
pPvfsStat->s_crtime = pSbuf->st_mtime;
pPvfsStat->s_blksize = pSbuf->st_blksize;
pPvfsStat->s_blocks = pSbuf->st_blocks;
return ntError;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysStat(
PCSTR pszFilename,
PPVFS_STAT pStat
)
{
NTSTATUS ntError = STATUS_SUCCESS;
struct stat sBuf = {0};
int unixerr = 0;
if (stat(pszFilename, &sBuf) == -1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
if (pStat) {
ntError = CopyUnixStatToPvfsStat(pStat, &sBuf);
BAIL_ON_NT_STATUS(ntError);
}
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysFstat(
int fd,
PPVFS_STAT pStat
)
{
NTSTATUS ntError = STATUS_SUCCESS;
struct stat sBuf = {0};
int unixerr = 0;
if (fstat(fd, &sBuf) == -1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
if (pStat) {
ntError = CopyUnixStatToPvfsStat(pStat, &sBuf);
BAIL_ON_NT_STATUS(ntError);
}
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysOpen(
int *pFd,
PSTR pszFilename,
int iFlags,
mode_t Mode
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int fd = -1;
int unixerr = 0;
BAIL_ON_INVALID_PTR(pszFilename, ntError);
if ((fd = open(pszFilename, iFlags, Mode)) == -1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
*pFd = fd;
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysMkDir(
PSTR pszDirname,
mode_t mode
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
if ((mkdir(pszDirname, mode)) == -1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysOpenDir(
PCSTR pszDirname,
DIR **ppDir
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
DIR *pDir = NULL;
if ((pDir = opendir(pszDirname)) == NULL) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
*ppDir = pDir;
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysDirFd(
PPVFS_CCB pCcb,
int *pFd
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
int fd = -1;
#ifdef HAVE_DIRFD
if ((fd = dirfd(pCcb->pDirContext->pDir)) == -1)
{
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
#else
if ((fd = open(pCcb->pszFilename, 0, 0)) == -1)
{
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
#endif
*pFd = fd;
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysReadDir(
DIR *pDir,
struct dirent **ppDirEntry
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
struct dirent *pDirEntry = NULL;
if ((pDirEntry = readdir(pDir)) == NULL)
{
/* Handle errno a little differently here. Assume
we can only get EBADF in the case on an error.
Otherwise, assume NULL means end-of-file. */
unixerr = errno;
if (unixerr == EBADF) {
ntError = PvfsMapUnixErrnoToNtStatus(unixerr);
BAIL_ON_NT_STATUS(ntError);
}
}
*ppDirEntry = pDirEntry;
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysCloseDir(
DIR *pDir
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
if (closedir(pDir) == -1)
{
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysClose(
int fd
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
if (close(fd) == -1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysLseek(
IN int fd,
IN off_t offset,
IN int whence,
OUT OPTIONAL off_t *pNewOffset
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
off_t newOffset = 0;
if ((newOffset = lseek(fd, offset, whence)) == (off_t)-1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
if (pNewOffset) {
*pNewOffset = newOffset;
}
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysFtruncate(
int fd,
off_t offset
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
if (ftruncate(fd, offset) == -1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysUtime(
PSTR pszPathname,
LONG64 LastWriteTime,
LONG64 LastAccessTime
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr;
time_t tWrite = 0;
time_t tAccess = 0;
struct utimbuf TimeBuf = {0};
PVFS_ZERO_MEMORY(&TimeBuf);
if (LastWriteTime != 0) {
ntError = PvfsWinToUnixTime(&tWrite, LastWriteTime);
BAIL_ON_NT_STATUS(ntError);
}
if (LastAccessTime != 0) {
ntError = PvfsWinToUnixTime(&tAccess, LastAccessTime);
BAIL_ON_NT_STATUS(ntError);
}
TimeBuf.actime = tAccess;
TimeBuf.modtime = tWrite;
if (utime(pszPathname, &TimeBuf) == -1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysFstatFs(
PPVFS_CCB pCcb,
PPVFS_STATFS pStatFs
)
{
NTSTATUS ntError = STATUS_SUCCESS;
#if defined(HAVE_FSTATFS) && defined(__LWI_LINUX__)
{
struct statfs sFsBuf;
int unixerr = 0;
if (fstatfs(pCcb->fd, &sFsBuf) == -1)
{
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
pStatFs->BlockSize = sFsBuf.f_bsize;
pStatFs->TotalBlocks = sFsBuf.f_blocks;
pStatFs->TotalFreeBlocks = sFsBuf.f_bavail;
pStatFs->MaximumNameLength = sFsBuf.f_namelen;
ntError = STATUS_SUCCESS;
}
#else
/* Make up some numbers */
pStatFs->BlockSize = 4096;
pStatFs->TotalBlocks = 1024*128;
pStatFs->TotalFreeBlocks = 1024*64;
pStatFs->MaximumNameLength = 255;
ntError = STATUS_SUCCESS;
BAIL_ON_NT_STATUS(ntError);
#endif
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysRemove(
PSTR pszPath
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
if (remove(pszPath) == -1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysRead(
PPVFS_CCB pCcb,
PVOID pBuffer,
ULONG pBufLen,
PLONG64 pOffset,
PULONG pBytesRead
)
{
NTSTATUS ntError = STATUS_SUCCESS;
ssize_t bytesRead = 0;
int unixerr = 0;
/* Use pread() if we have an offset, otherwise fall back
to read() */
if (pOffset)
{
off_t offset = 0;
bytesRead = pread(pCcb->fd, pBuffer, pBufLen, *pOffset);
if (bytesRead > 0)
{
/* pread() and pwrite() don't update the file offset */
ntError = PvfsSysLseek(pCcb->fd, bytesRead, SEEK_CUR, &offset);
BAIL_ON_NT_STATUS(ntError);
}
}
else
{
bytesRead = read(pCcb->fd, pBuffer, pBufLen);
}
if (bytesRead == -1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
*pBytesRead = (ULONG)bytesRead;
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysWrite(
PPVFS_CCB pCcb,
PVOID pBuffer,
ULONG pBufLen,
PLONG64 pOffset,
PULONG pBytesWritten
)
{
NTSTATUS ntError = STATUS_SUCCESS;
ssize_t bytesWritten = 0;
int unixerr = 0;
/* Use pwrite() if we have an offset, otherwise fall back
to write() */
if (pOffset)
{
off_t offset = 0;
bytesWritten = pwrite(pCcb->fd, pBuffer, pBufLen, *pOffset);
if (bytesWritten > 0)
{
/* pread() and pwrite() don't update the file offset */
ntError = PvfsSysLseek(pCcb->fd, bytesWritten, SEEK_CUR, &offset);
BAIL_ON_NT_STATUS(ntError);
}
}
else
{
bytesWritten = write(pCcb->fd, pBuffer, pBufLen);
}
if (bytesWritten == -1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
*pBytesWritten = (ULONG)bytesWritten;
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysChown(
PPVFS_CCB pCcb,
uid_t uid,
gid_t gid
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
if (chown(pCcb->pszFilename, uid, gid) == -1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysFchmod(
PPVFS_CCB pCcb,
mode_t Mode
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
if (fchmod(pCcb->fd, Mode) == -1) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysRename(
PCSTR pszOldname,
PCSTR pszNewname
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
if (rename(pszOldname, pszNewname) == -1 ) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
#define PVFS_DISABLE_FSYNC 1
NTSTATUS
PvfsSysFsync(
PPVFS_CCB pCcb
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
#ifdef PVFS_DISABLE_FSYNC
ntError = STATUS_SUCCESS;
unixerr = 0;
BAIL_ON_NT_STATUS(ntError);
#elif defined(HAVE_FDATASYNC)
if (fdatasync(pCcb->fd) == -1 ) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
#elif defined(HAVE_FSYNC)
if (fsync(pCcb->fd) == -1 ) {
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
#else
ntError = STATUS_NOT_SUPPORTED;
BAIL_ON_NT_STATUS(ntError);
#endif
cleanup:
return ntError;
error:
goto cleanup;
}
/**********************************************************
*********************************************************/
NTSTATUS
PvfsSysNanoSleep(
const struct timespec *pRequestedTime,
struct timespec *pRemainingTime
)
{
NTSTATUS ntError = STATUS_SUCCESS;
int unixerr = 0;
if (nanosleep(pRequestedTime, pRemainingTime) == -1)
{
PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
}
cleanup:
return ntError;
error:
goto cleanup;
}
/*
local variables:
mode: c
c-basic-offset: 4
indent-tabs-mode: nil
tab-width: 4
end:
*/