Blame sysdeps/unix/sysv/linux/internal_statvfs.c

Packit 6c4009
/* Copyright (C) 1998-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <assert.h>
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <mntent.h>
Packit 6c4009
#include <paths.h>
Packit 6c4009
#include <stdbool.h>
Packit 6c4009
#include <stdio_ext.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <sys/mount.h>
Packit 6c4009
#include <sys/stat.h>
Packit 6c4009
#include <sys/statfs.h>
Packit 6c4009
#include "internal_statvfs.h"
Packit 6c4009
#include "linux_fsinfo.h"
Packit 6c4009
#include <kernel-features.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Special internal-only bit value.  */
Packit 6c4009
#define ST_VALID 0x0020
Packit 6c4009
Packit 6c4009
Packit 6c4009
#ifndef STATFS
Packit 6c4009
# define STATFS statfs
Packit 6c4009
# define STATVFS statvfs
Packit 6c4009
# define INTERNAL_STATVFS __internal_statvfs
Packit 6c4009
#else
Packit 6c4009
extern int __statvfs_getflags (const char *name, int fstype, int fd);
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
INTERNAL_STATVFS (const char *name, struct STATVFS *buf,
Packit 6c4009
		  struct STATFS *fsbuf, int fd)
Packit 6c4009
{
Packit 6c4009
  /* Now fill in the fields we have information for.  */
Packit 6c4009
  buf->f_bsize = fsbuf->f_bsize;
Packit 6c4009
  /* Linux has the f_frsize size only in later version of the kernel.
Packit 6c4009
     If the value is not filled in use f_bsize.  */
Packit 6c4009
  buf->f_frsize = fsbuf->f_frsize ?: fsbuf->f_bsize;
Packit 6c4009
  buf->f_blocks = fsbuf->f_blocks;
Packit 6c4009
  buf->f_bfree = fsbuf->f_bfree;
Packit 6c4009
  buf->f_bavail = fsbuf->f_bavail;
Packit 6c4009
  buf->f_files = fsbuf->f_files;
Packit 6c4009
  buf->f_ffree = fsbuf->f_ffree;
Packit 6c4009
  if (sizeof (buf->f_fsid) == sizeof (fsbuf->f_fsid))
Packit 6c4009
    /* The shifting uses 'unsigned long long int' even though the target
Packit 6c4009
       field might only have 32 bits.  This is OK since the 'if' branch
Packit 6c4009
       is not used in this case but the compiler would still generate
Packit 6c4009
       warnings.  */
Packit 6c4009
    buf->f_fsid = ((fsbuf->f_fsid.__val[0]
Packit 6c4009
		    & ((1ULL << (8 * sizeof (fsbuf->f_fsid.__val[0]))) - 1))
Packit 6c4009
		   | ((unsigned long long int) fsbuf->f_fsid.__val[1]
Packit 6c4009
		      << (8 * (sizeof (buf->f_fsid)
Packit 6c4009
			       - sizeof (fsbuf->f_fsid.__val[0])))));
Packit 6c4009
  else
Packit 6c4009
    /* We cannot help here.  The statvfs element is not large enough to
Packit 6c4009
       contain both words of the statfs f_fsid field.  */
Packit 6c4009
    buf->f_fsid = fsbuf->f_fsid.__val[0];
Packit 6c4009
#ifdef _STATVFSBUF_F_UNUSED
Packit 6c4009
  buf->__f_unused = 0;
Packit 6c4009
#endif
Packit 6c4009
  buf->f_namemax = fsbuf->f_namelen;
Packit 6c4009
  memset (buf->__f_spare, '\0', sizeof (buf->__f_spare));
Packit 6c4009
Packit 6c4009
  /* What remains to do is to fill the fields f_favail and f_flag.  */
Packit 6c4009
Packit 6c4009
  /* XXX I have no idea how to compute f_favail.  Any idea???  */
Packit 6c4009
  buf->f_favail = buf->f_ffree;
Packit 6c4009
Packit 6c4009
  buf->f_flag = fsbuf->f_flags ^ ST_VALID;
Packit 6c4009
}