/*
* Copyright (c) 2003-2005 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: freediskspace.c,v 1.9 2005/03/17 22:09:36 ca Exp $")
#include "sm/types.h"
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/statfs.h"
#include "sm/limits.h"
/*
** FREEDISKSPACE -- see how much free space is on the queue filesystem
**
** Only implemented if you have statfs.
**
** Parameters:
** dir -- the directory in question.
** bsize -- (pointer to) filesystem block size (output)
** pkbfree -- (pointer to) free space (KB) (output)
**
** Returns:
** The number of blocks free on the queue filesystem.
** sm_err_temp(errno) if the statfs call fails.
**
** Side Effects:
** Puts the filesystem block size into bsize (if not NULL)
**
** Last code review: 2005-03-17 21:24:24
** Last code change:
*/
sm_ret_T
freediskspace(const char *dir, ulong *bsize, ulong *pkbfree)
{
ulong kbfree;
#if WIN32
ULARGE_INTEGER i64FreeBytesToCaller;
ULARGE_INTEGER i64TotalBytes;
extern void _dosmaperr(ULONG);
SM_ASSERT(pkbfree != NULL);
/* initialize */
(void) memset(&i64FreeBytesToCaller, 0, sizeof(i64FreeBytesToCaller));
(void) memset(&i64TotalBytes, 0, sizeof(i64TotalBytes));
if (bsize != NULL)
*bsize = ONEKB;
/* get the free disk space available */
if (GetDiskFreeSpaceEx(dir, (PULARGE_INTEGER) &i64FreeBytesToCaller,
(PULARGE_INTEGER) &i64TotalBytes, NULL))
{
/* convert to Kb, watch out for overflow */
if ((i64FreeBytesToCaller.QuadPart / ONEKB) > ULONG_MAX)
*pkbfree = ULONG_MAX;
else
*pkbfree = (ulong)
(i64FreeBytesToCaller.QuadPart / ONEKB);
return SM_SUCCESS;
}
return sm_err_temp(GetLastError());
#else /* WIN32 */
# if SFS_TYPE == SFS_USTAT
struct ustat fs;
struct stat statbuf;
# define FSBLOCKSIZE DEV_BSIZE
# define SFS_BAVAIL f_tfree
# else /* SFS_TYPE == SFS_USTAT */
# if defined(ultrix)
struct fs_data fs;
# define SFS_BAVAIL fd_bfreen
# define FSBLOCKSIZE 1024L
# else /* defined(ultrix) */
# if SFS_TYPE == SFS_STATVFS
struct statvfs fs;
# define FSBLOCKSIZE fs.f_frsize
# else /* SFS_TYPE == SFS_STATVFS */
struct statfs fs;
# define FSBLOCKSIZE fs.f_bsize
# endif /* SFS_TYPE == SFS_STATVFS */
# endif /* defined(ultrix) */
# endif /* SFS_TYPE == SFS_USTAT */
# ifndef SFS_BAVAIL
# define SFS_BAVAIL f_bavail
# endif /* ! SFS_BAVAIL */
SM_ASSERT(pkbfree != NULL);
# if SFS_TYPE == SFS_USTAT
if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
# else /* SFS_TYPE == SFS_USTAT */
# if SFS_TYPE == SFS_4ARGS
if (statfs(dir, &fs, sizeof fs, 0) == 0)
# else /* SFS_TYPE == SFS_4ARGS */
# if SFS_TYPE == SFS_STATVFS
if (statvfs(dir, &fs) == 0)
# else /* SFS_TYPE == SFS_STATVFS */
# if defined(ultrix)
if (statfs(dir, &fs) > 0)
# else /* defined(ultrix) */
if (statfs(dir, &fs) == 0)
# endif /* defined(ultrix) */
# endif /* SFS_TYPE == SFS_STATVFS */
# endif /* SFS_TYPE == SFS_4ARGS */
# endif /* SFS_TYPE == SFS_USTAT */
{
if (bsize != NULL)
*bsize = FSBLOCKSIZE;
if (fs.SFS_BAVAIL <= 0)
return 0;
else
{
if (fs.SFS_BAVAIL > ULONG_MAX)
kbfree = (ulong) ULONG_MAX;
else
kbfree = (ulong) fs.SFS_BAVAIL;
if (FSBLOCKSIZE > ONEKB)
kbfree *= FSBLOCKSIZE / ONEKB;
else if (FSBLOCKSIZE < ONEKB)
kbfree /= ONEKB / FSBLOCKSIZE;
*pkbfree = kbfree;
return SM_SUCCESS;
}
}
return sm_err_temp(errno);
}
#endif /* WIN32 */
syntax highlighted by Code2HTML, v. 0.9.1