|
Packit |
352660 |
/*
|
|
Packit |
352660 |
* Copyright © 2000 Keith Packard
|
|
Packit |
352660 |
* Copyright © 2005 Patrick Lam
|
|
Packit |
352660 |
*
|
|
Packit |
352660 |
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
Packit |
352660 |
* documentation for any purpose is hereby granted without fee, provided that
|
|
Packit |
352660 |
* the above copyright notice appear in all copies and that both that
|
|
Packit |
352660 |
* copyright notice and this permission notice appear in supporting
|
|
Packit |
352660 |
* documentation, and that the name of the author(s) not be used in
|
|
Packit |
352660 |
* advertising or publicity pertaining to distribution of the software without
|
|
Packit |
352660 |
* specific, written prior permission. The authors make no
|
|
Packit |
352660 |
* representations about the suitability of this software for any purpose. It
|
|
Packit |
352660 |
* is provided "as is" without express or implied warranty.
|
|
Packit |
352660 |
*
|
|
Packit |
352660 |
* THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
Packit |
352660 |
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
Packit |
352660 |
* EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
Packit |
352660 |
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
Packit |
352660 |
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
Packit |
352660 |
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
Packit |
352660 |
* PERFORMANCE OF THIS SOFTWARE.
|
|
Packit |
352660 |
*/
|
|
Packit |
352660 |
#include "fcint.h"
|
|
Packit |
352660 |
#include "fcarch.h"
|
|
Packit |
352660 |
#include <dirent.h>
|
|
Packit |
352660 |
#include <limits.h>
|
|
Packit |
352660 |
#include <sys/types.h>
|
|
Packit |
352660 |
#include <sys/stat.h>
|
|
Packit |
352660 |
#include <fcntl.h>
|
|
Packit |
352660 |
#ifdef HAVE_SYS_VFS_H
|
|
Packit |
352660 |
#include <sys/vfs.h>
|
|
Packit |
352660 |
#endif
|
|
Packit |
352660 |
#ifdef HAVE_SYS_STATVFS_H
|
|
Packit |
352660 |
#include <sys/statvfs.h>
|
|
Packit |
352660 |
#endif
|
|
Packit |
352660 |
#ifdef HAVE_SYS_STATFS_H
|
|
Packit |
352660 |
#include <sys/statfs.h>
|
|
Packit |
352660 |
#endif
|
|
Packit |
352660 |
#ifdef HAVE_SYS_PARAM_H
|
|
Packit |
352660 |
#include <sys/param.h>
|
|
Packit |
352660 |
#endif
|
|
Packit |
352660 |
#ifdef HAVE_SYS_MOUNT_H
|
|
Packit |
352660 |
#include <sys/mount.h>
|
|
Packit |
352660 |
#endif
|
|
Packit |
352660 |
#include <errno.h>
|
|
Packit |
352660 |
|
|
Packit |
352660 |
#ifdef _WIN32
|
|
Packit |
352660 |
#ifdef __GNUC__
|
|
Packit |
352660 |
typedef long long INT64;
|
|
Packit |
352660 |
#define EPOCH_OFFSET 11644473600ll
|
|
Packit |
352660 |
#else
|
|
Packit |
352660 |
#define EPOCH_OFFSET 11644473600i64
|
|
Packit |
352660 |
typedef __int64 INT64;
|
|
Packit |
352660 |
#endif
|
|
Packit |
352660 |
|
|
Packit |
352660 |
/* Workaround for problems in the stat() in the Microsoft C library:
|
|
Packit |
352660 |
*
|
|
Packit |
352660 |
* 1) stat() uses FindFirstFile() to get the file
|
|
Packit |
352660 |
* attributes. Unfortunately this API doesn't return correct values
|
|
Packit |
352660 |
* for modification time of a directory until some time after a file
|
|
Packit |
352660 |
* or subdirectory has been added to the directory. (This causes
|
|
Packit |
352660 |
* run-test.sh to fail, for instance.) GetFileAttributesEx() is
|
|
Packit |
352660 |
* better, it returns the updated timestamp right away.
|
|
Packit |
352660 |
*
|
|
Packit |
352660 |
* 2) stat() does some strange things related to backward
|
|
Packit |
352660 |
* compatibility with the local time timestamps on FAT volumes and
|
|
Packit |
352660 |
* daylight saving time. This causes problems after the switches
|
|
Packit |
352660 |
* to/from daylight saving time. See
|
|
Packit |
352660 |
* http://bugzilla.gnome.org/show_bug.cgi?id=154968 , especially
|
|
Packit |
352660 |
* comment #30, and http://www.codeproject.com/datetime/dstbugs.asp .
|
|
Packit |
352660 |
* We don't need any of that, FAT and Win9x are as good as dead. So
|
|
Packit |
352660 |
* just use the UTC timestamps from NTFS, converted to the Unix epoch.
|
|
Packit |
352660 |
*/
|
|
Packit |
352660 |
|
|
Packit |
352660 |
int
|
|
Packit |
352660 |
FcStat (const FcChar8 *file, struct stat *statb)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
WIN32_FILE_ATTRIBUTE_DATA wfad;
|
|
Packit |
352660 |
char full_path_name[MAX_PATH];
|
|
Packit |
352660 |
char *basename;
|
|
Packit |
352660 |
DWORD rc;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
if (!GetFileAttributesEx ((LPCSTR) file, GetFileExInfoStandard, &wfad))
|
|
Packit |
352660 |
return -1;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
statb->st_dev = 0;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
/* Calculate a pseudo inode number as a hash of the full path name.
|
|
Packit |
352660 |
* Call GetLongPathName() to get the spelling of the path name as it
|
|
Packit |
352660 |
* is on disk.
|
|
Packit |
352660 |
*/
|
|
Packit |
352660 |
rc = GetFullPathName ((LPCSTR) file, sizeof (full_path_name), full_path_name, &basename);
|
|
Packit |
352660 |
if (rc == 0 || rc > sizeof (full_path_name))
|
|
Packit |
352660 |
return -1;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
rc = GetLongPathName (full_path_name, full_path_name, sizeof (full_path_name));
|
|
Packit |
352660 |
statb->st_ino = FcStringHash ((const FcChar8 *) full_path_name);
|
|
Packit |
352660 |
|
|
Packit |
352660 |
statb->st_mode = _S_IREAD | _S_IWRITE;
|
|
Packit |
352660 |
statb->st_mode |= (statb->st_mode >> 3) | (statb->st_mode >> 6);
|
|
Packit |
352660 |
|
|
Packit |
352660 |
if (wfad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
Packit |
352660 |
statb->st_mode |= _S_IFDIR;
|
|
Packit |
352660 |
else
|
|
Packit |
352660 |
statb->st_mode |= _S_IFREG;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
statb->st_nlink = 1;
|
|
Packit |
352660 |
statb->st_uid = statb->st_gid = 0;
|
|
Packit |
352660 |
statb->st_rdev = 0;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
if (wfad.nFileSizeHigh > 0)
|
|
Packit |
352660 |
return -1;
|
|
Packit |
352660 |
statb->st_size = wfad.nFileSizeLow;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
statb->st_atime = (*(INT64 *)&wfad.ftLastAccessTime)/10000000 - EPOCH_OFFSET;
|
|
Packit |
352660 |
statb->st_mtime = (*(INT64 *)&wfad.ftLastWriteTime)/10000000 - EPOCH_OFFSET;
|
|
Packit |
352660 |
statb->st_ctime = statb->st_mtime;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
return 0;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
#else
|
|
Packit |
352660 |
|
|
Packit |
352660 |
int
|
|
Packit |
352660 |
FcStat (const FcChar8 *file, struct stat *statb)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
return stat ((char *) file, statb);
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
/* Adler-32 checksum implementation */
|
|
Packit |
352660 |
struct Adler32 {
|
|
Packit |
352660 |
int a;
|
|
Packit |
352660 |
int b;
|
|
Packit |
352660 |
};
|
|
Packit |
352660 |
|
|
Packit |
352660 |
static void
|
|
Packit |
352660 |
Adler32Init (struct Adler32 *ctx)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
ctx->a = 1;
|
|
Packit |
352660 |
ctx->b = 0;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
static void
|
|
Packit |
352660 |
Adler32Update (struct Adler32 *ctx, const char *data, int data_len)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
while (data_len--)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
ctx->a = (ctx->a + *data++) % 65521;
|
|
Packit |
352660 |
ctx->b = (ctx->b + ctx->a) % 65521;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
static int
|
|
Packit |
352660 |
Adler32Finish (struct Adler32 *ctx)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
return ctx->a + (ctx->b << 16);
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
|
|
Packit |
352660 |
/* dirent.d_type can be relied upon on FAT filesystem */
|
|
Packit |
352660 |
static FcBool
|
|
Packit |
352660 |
FcDirChecksumScandirFilter(const struct dirent *entry)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
return entry->d_type != DT_DIR;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
#endif
|
|
Packit |
352660 |
|
|
Packit |
352660 |
static int
|
|
Packit |
352660 |
FcDirChecksumScandirSorter(const struct dirent **lhs, const struct dirent **rhs)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
return strcmp((*lhs)->d_name, (*rhs)->d_name);
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
static void
|
|
Packit |
352660 |
free_dirent (struct dirent **p)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
struct dirent **x;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
for (x = p; *x != NULL; x++)
|
|
Packit |
352660 |
free (*x);
|
|
Packit |
352660 |
|
|
Packit |
352660 |
free (p);
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
int
|
|
Packit |
352660 |
FcScandir (const char *dirp,
|
|
Packit |
352660 |
struct dirent ***namelist,
|
|
Packit |
352660 |
int (*filter) (const struct dirent *),
|
|
Packit |
352660 |
int (*compar) (const struct dirent **, const struct dirent **));
|
|
Packit |
352660 |
|
|
Packit |
352660 |
int
|
|
Packit |
352660 |
FcScandir (const char *dirp,
|
|
Packit |
352660 |
struct dirent ***namelist,
|
|
Packit |
352660 |
int (*filter) (const struct dirent *),
|
|
Packit |
352660 |
int (*compar) (const struct dirent **, const struct dirent **))
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
DIR *d;
|
|
Packit |
352660 |
struct dirent *dent, *p, **dlist, **dlp;
|
|
Packit |
352660 |
size_t lsize = 128, n = 0;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
d = opendir (dirp);
|
|
Packit |
352660 |
if (!d)
|
|
Packit |
352660 |
return -1;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
dlist = (struct dirent **) malloc (sizeof (struct dirent *) * lsize);
|
|
Packit |
352660 |
if (!dlist)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
closedir (d);
|
|
Packit |
352660 |
errno = ENOMEM;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
return -1;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
*dlist = NULL;
|
|
Packit |
352660 |
while ((dent = readdir (d)))
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
if (!filter || (filter) (dent))
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
size_t dentlen = FcPtrToOffset (dent, dent->d_name) + strlen (dent->d_name) + 1;
|
|
Packit |
352660 |
dentlen = ((dentlen + ALIGNOF_VOID_P - 1) & ~(ALIGNOF_VOID_P - 1));
|
|
Packit |
352660 |
p = (struct dirent *) malloc (dentlen);
|
|
Packit |
352660 |
if (!p)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
free_dirent (dlist);
|
|
Packit |
352660 |
closedir (d);
|
|
Packit |
352660 |
errno = ENOMEM;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
return -1;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
memcpy (p, dent, dentlen);
|
|
Packit |
352660 |
if ((n + 1) >= lsize)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
lsize += 128;
|
|
Packit |
352660 |
dlp = (struct dirent **) realloc (dlist, sizeof (struct dirent *) * lsize);
|
|
Packit |
352660 |
if (!dlp)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
free (p);
|
|
Packit |
352660 |
free_dirent (dlist);
|
|
Packit |
352660 |
closedir (d);
|
|
Packit |
352660 |
errno = ENOMEM;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
return -1;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
dlist = dlp;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
dlist[n++] = p;
|
|
Packit |
352660 |
dlist[n] = NULL;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
closedir (d);
|
|
Packit |
352660 |
|
|
Packit |
352660 |
qsort (dlist, n, sizeof (struct dirent *), (int (*) (const void *, const void *))compar);
|
|
Packit |
352660 |
|
|
Packit |
352660 |
*namelist = dlist;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
return n;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
static int
|
|
Packit |
352660 |
FcDirChecksum (const FcChar8 *dir, time_t *checksum)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
struct Adler32 ctx;
|
|
Packit |
352660 |
struct dirent **files;
|
|
Packit |
352660 |
int n;
|
|
Packit |
352660 |
int ret = 0;
|
|
Packit |
352660 |
size_t len = strlen ((const char *)dir);
|
|
Packit |
352660 |
|
|
Packit |
352660 |
Adler32Init (&ctx;;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
n = FcScandir ((const char *)dir, &files,
|
|
Packit |
352660 |
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
|
|
Packit |
352660 |
&FcDirChecksumScandirFilter,
|
|
Packit |
352660 |
#else
|
|
Packit |
352660 |
NULL,
|
|
Packit |
352660 |
#endif
|
|
Packit |
352660 |
&FcDirChecksumScandirSorter);
|
|
Packit |
352660 |
if (n == -1)
|
|
Packit |
352660 |
return -1;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
while (n--)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
size_t dlen = strlen (files[n]->d_name);
|
|
Packit |
352660 |
int dtype;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
|
|
Packit |
352660 |
dtype = files[n]->d_type;
|
|
Packit |
352660 |
if (dtype == DT_UNKNOWN)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
#endif
|
|
Packit |
352660 |
struct stat statb;
|
|
Packit |
352660 |
char *f = malloc (len + 1 + dlen + 1);
|
|
Packit |
352660 |
|
|
Packit |
352660 |
if (!f)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
ret = -1;
|
|
Packit |
352660 |
goto bail;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
memcpy (f, dir, len);
|
|
Packit |
352660 |
f[len] = FC_DIR_SEPARATOR;
|
|
Packit |
352660 |
memcpy (&f[len + 1], files[n]->d_name, dlen);
|
|
Packit |
352660 |
f[len + 1 + dlen] = 0;
|
|
Packit |
352660 |
if (lstat (f, &statb) < 0)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
ret = -1;
|
|
Packit |
352660 |
free (f);
|
|
Packit |
352660 |
goto bail;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
if (S_ISDIR (statb.st_mode))
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
free (f);
|
|
Packit |
352660 |
goto bail;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
free (f);
|
|
Packit |
352660 |
dtype = statb.st_mode;
|
|
Packit |
352660 |
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
#endif
|
|
Packit |
352660 |
Adler32Update (&ctx, files[n]->d_name, dlen + 1);
|
|
Packit |
352660 |
Adler32Update (&ctx, (char *)&dtype, sizeof (int));
|
|
Packit |
352660 |
|
|
Packit |
352660 |
bail:
|
|
Packit |
352660 |
free (files[n]);
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
free (files);
|
|
Packit |
352660 |
if (ret == -1)
|
|
Packit |
352660 |
return -1;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
*checksum = Adler32Finish (&ctx;;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
return 0;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
#endif /* _WIN32 */
|
|
Packit |
352660 |
|
|
Packit |
352660 |
int
|
|
Packit |
352660 |
FcStatChecksum (const FcChar8 *file, struct stat *statb)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
if (FcStat (file, statb) == -1)
|
|
Packit |
352660 |
return -1;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
#ifndef _WIN32
|
|
Packit |
352660 |
/* We have a workaround of the broken stat() in FcStat() for Win32.
|
|
Packit |
352660 |
* No need to do something further more.
|
|
Packit |
352660 |
*/
|
|
Packit |
352660 |
if (FcIsFsMtimeBroken (file))
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
if (FcDirChecksum (file, &statb->st_mtime) == -1)
|
|
Packit |
352660 |
return -1;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
#endif
|
|
Packit |
352660 |
|
|
Packit |
352660 |
return 0;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
static int
|
|
Packit |
352660 |
FcFStatFs (int fd, FcStatFS *statb)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
const char *p = NULL;
|
|
Packit |
352660 |
int ret = -1;
|
|
Packit |
352660 |
FcBool flag = FcFalse;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
#if defined(HAVE_FSTATVFS) && (defined(HAVE_STRUCT_STATVFS_F_BASETYPE) || defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME))
|
|
Packit |
352660 |
struct statvfs buf;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
memset (statb, 0, sizeof (FcStatFS));
|
|
Packit |
352660 |
|
|
Packit |
352660 |
if ((ret = fstatvfs (fd, &buf)) == 0)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
# if defined(HAVE_STRUCT_STATVFS_F_BASETYPE)
|
|
Packit |
352660 |
p = buf.f_basetype;
|
|
Packit |
352660 |
# elif defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)
|
|
Packit |
352660 |
p = buf.f_fstypename;
|
|
Packit |
352660 |
# endif
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
#elif defined(HAVE_FSTATFS) && (defined(HAVE_STRUCT_STATFS_F_FLAGS) || defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) || defined(__linux__))
|
|
Packit |
352660 |
struct statfs buf;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
memset (statb, 0, sizeof (FcStatFS));
|
|
Packit |
352660 |
|
|
Packit |
352660 |
if ((ret = fstatfs (fd, &buf)) == 0)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
# if defined(HAVE_STRUCT_STATFS_F_FLAGS) && defined(MNT_LOCAL)
|
|
Packit |
352660 |
statb->is_remote_fs = !(buf.f_flags & MNT_LOCAL);
|
|
Packit |
352660 |
flag = FcTrue;
|
|
Packit |
352660 |
# endif
|
|
Packit |
352660 |
# if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME)
|
|
Packit |
352660 |
p = buf.f_fstypename;
|
|
Packit |
352660 |
# elif defined(__linux__)
|
|
Packit |
352660 |
switch (buf.f_type)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
case 0x6969: /* nfs */
|
|
Packit |
352660 |
statb->is_remote_fs = FcTrue;
|
|
Packit |
352660 |
break;
|
|
Packit |
352660 |
case 0x4d44: /* fat */
|
|
Packit |
352660 |
statb->is_mtime_broken = FcTrue;
|
|
Packit |
352660 |
break;
|
|
Packit |
352660 |
default:
|
|
Packit |
352660 |
break;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
return ret;
|
|
Packit |
352660 |
# else
|
|
Packit |
352660 |
# error "BUG: No way to figure out with fstatfs()"
|
|
Packit |
352660 |
# endif
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
#endif
|
|
Packit |
352660 |
if (p)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
if (!flag && strcmp (p, "nfs") == 0)
|
|
Packit |
352660 |
statb->is_remote_fs = FcTrue;
|
|
Packit |
352660 |
if (strcmp (p, "msdosfs") == 0 ||
|
|
Packit |
352660 |
strcmp (p, "pcfs") == 0)
|
|
Packit |
352660 |
statb->is_mtime_broken = FcTrue;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
return ret;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
FcBool
|
|
Packit |
352660 |
FcIsFsMmapSafe (int fd)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
FcStatFS statb;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
if (FcFStatFs (fd, &statb) < 0)
|
|
Packit |
352660 |
return FcTrue;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
return !statb.is_remote_fs;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
FcBool
|
|
Packit |
352660 |
FcIsFsMtimeBroken (const FcChar8 *dir)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
int fd = FcOpen ((const char *) dir, O_RDONLY);
|
|
Packit |
352660 |
|
|
Packit |
352660 |
if (fd != -1)
|
|
Packit |
352660 |
{
|
|
Packit |
352660 |
FcStatFS statb;
|
|
Packit |
352660 |
int ret = FcFStatFs (fd, &statb);
|
|
Packit |
352660 |
|
|
Packit |
352660 |
close (fd);
|
|
Packit |
352660 |
if (ret < 0)
|
|
Packit |
352660 |
return FcFalse;
|
|
Packit |
352660 |
|
|
Packit |
352660 |
return statb.is_mtime_broken;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
return FcFalse;
|
|
Packit |
352660 |
}
|
|
Packit |
352660 |
|
|
Packit |
352660 |
#define __fcstat__
|
|
Packit |
352660 |
#include "fcaliastail.h"
|
|
Packit |
352660 |
#undef __fcstat__
|