Add a generic scalb implementation
[glibc.git] / include / file_change_detection.h
blobaaed0a9b6d7d9594239acf2ceba61976198d90af
1 /* Detecting file changes using modification times.
2 Copyright (C) 2017-2020 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <errno.h>
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <stdio.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
26 /* Items for identifying a particular file version. Excerpt from
27 struct stat64. */
28 struct file_change_detection
30 /* Special values: 0 if file does not exist. -1 to force mismatch
31 with the next comparison. */
32 off64_t size;
34 ino64_t ino;
35 struct timespec mtime;
36 struct timespec ctime;
39 /* Returns true if *LEFT and *RIGHT describe the same version of the
40 same file. */
41 static bool __attribute__ ((unused))
42 file_is_unchanged (const struct file_change_detection *left,
43 const struct file_change_detection *right)
45 if (left->size < 0 || right->size < 0)
46 /* Negative sizes are used as markers and never match. */
47 return false;
48 else if (left->size == 0 && right->size == 0)
49 /* Both files are empty or do not exist, so they have the same
50 content, no matter what the other fields indicate. */
51 return true;
52 else
53 return left->size == right->size
54 && left->ino == right->ino
55 && left->mtime.tv_sec == right->mtime.tv_sec
56 && left->mtime.tv_nsec == right->mtime.tv_nsec
57 && left->ctime.tv_sec == right->ctime.tv_sec
58 && left->ctime.tv_nsec == right->ctime.tv_nsec;
61 /* Extract file change information to *FILE from the stat buffer
62 *ST. */
63 static void __attribute__ ((unused))
64 file_change_detection_for_stat (struct file_change_detection *file,
65 const struct stat64 *st)
67 if (S_ISDIR (st->st_mode))
68 /* Treat as empty file. */
69 file->size = 0;
70 else if (!S_ISREG (st->st_mode))
71 /* Non-regular files cannot be cached. */
72 file->size = -1;
73 else
75 file->size = st->st_size;
76 file->ino = st->st_ino;
77 file->mtime = st->st_mtim;
78 file->ctime = st->st_ctim;
82 /* Writes file change information for PATH to *FILE. Returns true on
83 success. For benign errors, *FILE is cleared, and true is
84 returned. For errors indicating resource outages and the like,
85 false is returned. */
86 static bool __attribute__ ((unused))
87 file_change_detection_for_path (struct file_change_detection *file,
88 const char *path)
90 struct stat64 st;
91 if (stat64 (path, &st) != 0)
92 switch (errno)
94 case EACCES:
95 case EISDIR:
96 case ELOOP:
97 case ENOENT:
98 case ENOTDIR:
99 case EPERM:
100 /* Ignore errors due to file system contents. Instead, treat
101 the file as empty. */
102 file->size = 0;
103 return true;
104 default:
105 /* Other errors are fatal. */
106 return false;
108 else /* stat64 was successfull. */
110 file_change_detection_for_stat (file, &st);
111 return true;
115 /* Writes file change information for the stream FP to *FILE. Returns
116 ture on success, false on failure. If FP is NULL, treat the file
117 as non-existing. */
118 static bool __attribute__ ((unused))
119 file_change_detection_for_fp (struct file_change_detection *file,
120 FILE *fp)
122 if (fp == NULL)
124 /* The file does not exist. */
125 file->size = 0;
126 return true;
128 else
130 struct stat64 st;
131 if (fstat64 (__fileno (fp), &st) != 0)
132 /* If we already have a file descriptor, all errors are fatal. */
133 return false;
134 else
136 file_change_detection_for_stat (file, &st);
137 return true;