Apache HTTPD
testfileinfo.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "apr_file_io.h"
18#include "apr_file_info.h"
19#include "apr_strings.h"
20#include "apr_errno.h"
21#include "apr_general.h"
22#include "apr_poll.h"
23#include "apr_lib.h"
24#include "testutil.h"
25
26#define FILENAME "data/file_datafile.txt"
27#define NEWFILENAME "data/new_datafile.txt"
28#define NEWFILEDATA "This is new text in a new file."
29
30static const struct view_fileinfo
31{
34} vfi[] = {
35 {APR_FINFO_MTIME, "MTIME"},
36 {APR_FINFO_CTIME, "CTIME"},
37 {APR_FINFO_ATIME, "ATIME"},
38 {APR_FINFO_SIZE, "SIZE"},
39 {APR_FINFO_DEV, "DEV"},
40 {APR_FINFO_INODE, "INODE"},
41 {APR_FINFO_NLINK, "NLINK"},
42 {APR_FINFO_TYPE, "TYPE"},
43 {APR_FINFO_USER, "USER"},
44 {APR_FINFO_GROUP, "GROUP"},
45 {APR_FINFO_UPROT, "UPROT"},
46 {APR_FINFO_GPROT, "GPROT"},
47 {APR_FINFO_WPROT, "WPROT"},
48 {0, NULL}
49};
50
52{
53 /* Minimum supported flags across all platforms (APR_FINFO_MIN) */
54 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_TYPE",
55 (f1->valid & f2->valid & APR_FINFO_TYPE));
56 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in filetype",
57 f1->filetype == f2->filetype);
58 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_SIZE",
59 (f1->valid & f2->valid & APR_FINFO_SIZE));
60 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in size",
61 f1->size == f2->size);
62 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_ATIME",
63 (f1->valid & f2->valid & APR_FINFO_ATIME));
64 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in atime",
65 f1->atime == f2->atime);
66 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_MTIME",
67 (f1->valid & f2->valid & APR_FINFO_MTIME));
68 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in mtime",
69 f1->mtime == f2->mtime);
70 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_CTIME",
71 (f1->valid & f2->valid & APR_FINFO_CTIME));
72 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in ctime",
73 f1->ctime == f2->ctime);
74
75 if (f1->valid & f2->valid & APR_FINFO_NAME)
76 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in name",
77 !strcmp(f1->name, f2->name));
78 if (f1->fname && f2->fname)
79 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in fname",
80 !strcmp(f1->fname, f2->fname));
81
82 /* Additional supported flags not supported on all platforms */
83 if (f1->valid & f2->valid & APR_FINFO_USER)
84 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in user",
85 !apr_uid_compare(f1->user, f2->user));
86 if (f1->valid & f2->valid & APR_FINFO_GROUP)
87 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in group",
88 !apr_gid_compare(f1->group, f2->group));
89 if (f1->valid & f2->valid & APR_FINFO_INODE)
90 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in inode",
91 f1->inode == f2->inode);
92 if (f1->valid & f2->valid & APR_FINFO_DEV)
93 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in device",
94 f1->device == f2->device);
95 if (f1->valid & f2->valid & APR_FINFO_NLINK)
96 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in nlink",
97 f1->nlink == f2->nlink);
98 if (f1->valid & f2->valid & APR_FINFO_CSIZE)
99 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in csize",
100 f1->csize == f2->csize);
101 if (f1->valid & f2->valid & APR_FINFO_PROT)
102 ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in protection",
103 f1->protection == f2->protection);
104}
105
106static void test_info_get(abts_case *tc, void *data)
107{
109 apr_finfo_t finfo;
110 apr_status_t rv;
111
114
116 if (APR_STATUS_IS_INCOMPLETE(rv)) {
117 char *str;
118 int i;
119 str = apr_pstrdup(p, "APR_INCOMPLETE: Missing ");
120 for (i = 0; vfi[i].bits; ++i) {
121 if (vfi[i].bits & ~finfo.valid) {
122 str = apr_pstrcat(p, str, vfi[i].description, " ", NULL);
123 }
124 }
125 ABTS_FAIL(tc, str);
126 }
129}
130
131static void test_stat(abts_case *tc, void *data)
132{
133 apr_finfo_t finfo;
134 apr_status_t rv;
135
136 rv = apr_stat(&finfo, FILENAME, APR_FINFO_NORM, p);
137 if (APR_STATUS_IS_INCOMPLETE(rv)) {
138 char *str;
139 int i;
140 str = apr_pstrdup(p, "APR_INCOMPLETE: Missing ");
141 for (i = 0; vfi[i].bits; ++i) {
142 if (vfi[i].bits & ~finfo.valid) {
143 str = apr_pstrcat(p, str, vfi[i].description, " ", NULL);
144 }
145 }
146 ABTS_FAIL(tc, str);
147 }
149}
150
151static void test_stat_eq_finfo(abts_case *tc, void *data)
152{
154 apr_finfo_t finfo;
156 apr_status_t rv;
157
161
162 /* Opening the file may have toggled the atime member (time last
163 * accessed), so fetch our apr_stat() after getting the fileinfo
164 * of the open file...
165 */
168
170
171 finfo_equal(tc, &stat_finfo, &finfo);
172}
173
175{
176 const apr_size_t data_len = strlen(NEWFILEDATA);
178 apr_finfo_t finfo;
179 apr_status_t rv;
181
186 APR_ASSERT_SUCCESS(tc, "open file", rv);
187
188 /* A funny thing happened to me the other day: I wrote something
189 * into a buffered file, then asked for its size using
190 * apr_file_info_get; and guess what? The size was 0! That's not a
191 * nice way to behave.
192 */
193 bytes = data_len;
195 APR_ASSERT_SUCCESS(tc, "write file contents", rv);
196 ABTS_TRUE(tc, data_len == bytes);
197
199 APR_ASSERT_SUCCESS(tc, "get file size", rv);
200 ABTS_TRUE(tc, bytes == (apr_size_t) finfo.size);
202}
203
204static void test_mtime_set(abts_case *tc, void *data)
205{
207 apr_finfo_t finfo;
208 apr_time_t epoch = 0;
209 apr_status_t rv;
210
211 /* This test sort of depends on the system clock being at least
212 * marginally ccorrect; We'll be setting the modification time to
213 * the epoch.
214 */
219 APR_ASSERT_SUCCESS(tc, "open file", rv);
220
221 /* Check that the current mtime is not the epoch */
222 rv = apr_stat(&finfo, NEWFILENAME, APR_FINFO_MTIME, p);
223 if (APR_STATUS_IS_INCOMPLETE(rv)) {
224 char *str;
225 int i;
226 str = apr_pstrdup(p, "APR_INCOMPLETE: Missing ");
227 for (i = 0; vfi[i].bits; ++i) {
228 if (vfi[i].bits & ~finfo.valid) {
229 str = apr_pstrcat(p, str, vfi[i].description, " ", NULL);
230 }
231 }
232 ABTS_FAIL(tc, str);
233 }
234 APR_ASSERT_SUCCESS(tc, "get initial mtime", rv);
235 ABTS_TRUE(tc, finfo.mtime != epoch);
236
237 /* Reset the mtime to the epoch and verify the result.
238 * Note: we blindly assume that if the first apr_stat succeeded,
239 * the second one will, too.
240 */
242 APR_ASSERT_SUCCESS(tc, "set mtime", rv);
243
244 rv = apr_stat(&finfo, NEWFILENAME, APR_FINFO_MTIME, p);
245 APR_ASSERT_SUCCESS(tc, "get modified mtime", rv);
246 ABTS_TRUE(tc, finfo.mtime == epoch);
247
249}
250
252{
253 suite = ADD_SUITE(suite)
254
260
261 return suite;
262}
263
void abts_run_test(abts_suite *ts, test_func f, void *value)
Definition abts.c:175
#define ABTS_TRUE(a, b)
Definition abts.h:127
#define ADD_SUITE(suite)
Definition abts.h:67
#define ABTS_ASSERT(a, b, c)
Definition abts.h:130
#define ABTS_INT_EQUAL(a, b, c)
Definition abts.h:109
#define ABTS_FAIL(a, b)
Definition abts.h:128
#define APR_ASSERT_SUCCESS(tc, ctxt, rv)
Definition testutil.h:58
APR Error Codes.
APR File Information.
APR File I/O Handling.
APR Miscellaneous library routines.
APR general purpose library routines.
APR Poll interface.
#define f2(x, y, z)
Definition apr_sha1.c:64
#define f1(x, y, z)
Definition apr_sha1.c:63
APR Strings library.
#define APR_STATUS_IS_INCOMPLETE(s)
Definition apr_errno.h:542
const char const apr_size_t data_len
apr_size_t size
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
apr_file_t * thefile
void * data
#define APR_FOPEN_TRUNCATE
Definition apr_file_io.h:58
#define APR_FOPEN_DELONCLOSE
Definition apr_file_io.h:66
#define APR_FOPEN_BUFFERED
Definition apr_file_io.h:65
#define APR_FOPEN_WRITE
Definition apr_file_io.h:55
#define APR_FOPEN_READ
Definition apr_file_io.h:54
#define APR_FOPEN_CREATE
Definition apr_file_io.h:56
#define APR_OS_DEFAULT
#define APR_FINFO_DEV
#define APR_FINFO_ATIME
#define APR_FINFO_INODE
#define APR_FINFO_USER
#define APR_FINFO_NAME
#define APR_FINFO_GROUP
#define APR_FINFO_CTIME
#define APR_FINFO_MTIME
#define APR_FINFO_WPROT
#define APR_FINFO_NLINK
#define APR_FINFO_UPROT
#define APR_FINFO_NORM
#define APR_FINFO_TYPE
#define APR_FINFO_PROT
#define APR_FINFO_SIZE
#define APR_FINFO_GPROT
#define APR_FINFO_CSIZE
const void apr_size_t bytes
Definition apr_random.h:91
apr_int64_t apr_time_t
Definition apr_time.h:45
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
apr_off_t size
apr_time_t mtime
apr_int32_t valid
char * description
apr_int32_t bits
#define NEWFILEDATA
static void test_buffered_write_size(abts_case *tc, void *data)
static void test_stat_eq_finfo(abts_case *tc, void *data)
static void test_stat(abts_case *tc, void *data)
static void test_mtime_set(abts_case *tc, void *data)
#define FILENAME
abts_suite * testfileinfo(abts_suite *suite)
static void finfo_equal(abts_case *tc, apr_finfo_t *f1, apr_finfo_t *f2)
static void test_info_get(abts_case *tc, void *data)
#define NEWFILENAME
static const struct view_fileinfo vfi[]
#define str