/* * 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 */