Commit | Line | Data |
---|---|---|
184e8823 | 1 | /* $Cambridge: exim/src/src/lookups/dsearch.c,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */ |
0756eb3c PH |
2 | |
3 | /************************************************* | |
4 | * Exim - an Internet mail transport agent * | |
5 | *************************************************/ | |
6 | ||
184e8823 | 7 | /* Copyright (c) University of Cambridge 1995 - 2007 */ |
0756eb3c PH |
8 | /* See the file NOTICE for conditions of use and distribution. */ |
9 | ||
10 | /* The idea for this code came from Matthew Byng-Maddick, but his original has | |
11 | been heavily reworked a lot for Exim 4 (and it now uses stat() rather than a | |
12 | directory scan). */ | |
13 | ||
14 | ||
15 | #include "../exim.h" | |
16 | #include "lf_functions.h" | |
17 | #include "dsearch.h" | |
18 | ||
19 | ||
20 | ||
21 | /************************************************* | |
22 | * Open entry point * | |
23 | *************************************************/ | |
24 | ||
25 | /* See local README for interface description. We open the directory to test | |
26 | whether it exists and whether it is searchable. However, we don't need to keep | |
27 | it open, because the "search" can be done by a call to stat() rather than | |
28 | actually scanning through the list of files. */ | |
29 | ||
30 | void * | |
31 | dsearch_open(uschar *dirname, uschar **errmsg) | |
32 | { | |
33 | DIR *dp = opendir(CS dirname); | |
34 | if (dp == NULL) | |
35 | { | |
36 | int save_errno = errno; | |
37 | *errmsg = string_open_failed(errno, "%s for directory search", dirname); | |
38 | errno = save_errno; | |
39 | return NULL; | |
40 | } | |
41 | closedir(dp); | |
42 | return (void *)(-1); | |
43 | } | |
44 | ||
45 | ||
46 | /************************************************* | |
47 | * Check entry point * | |
48 | *************************************************/ | |
49 | ||
50 | /* The handle will always be (void *)(-1), but don't try casting it to an | |
51 | integer as this gives warnings on 64-bit systems. */ | |
52 | ||
53 | BOOL | |
54 | dsearch_check(void *handle, uschar *filename, int modemask, uid_t *owners, | |
55 | gid_t *owngroups, uschar **errmsg) | |
56 | { | |
57 | handle = handle; | |
58 | return lf_check_file(-1, filename, S_IFDIR, modemask, owners, owngroups, | |
59 | "dsearch", errmsg) == 0; | |
60 | } | |
61 | ||
62 | ||
63 | /************************************************* | |
64 | * Find entry point * | |
65 | *************************************************/ | |
66 | ||
67 | /* See local README for interface description. We use stat() instead of | |
68 | scanning the directory, as it is hopefully faster to let the OS do the scanning | |
69 | for us. */ | |
70 | ||
71 | int | |
72 | dsearch_find(void *handle, uschar *dirname, uschar *keystring, int length, | |
73 | uschar **result, uschar **errmsg, BOOL *do_cache) | |
74 | { | |
75 | struct stat statbuf; | |
76 | int save_errno; | |
77 | uschar filename[PATH_MAX]; | |
78 | ||
79 | handle = handle; /* Keep picky compilers happy */ | |
80 | length = length; | |
81 | do_cache = do_cache; | |
82 | ||
83 | if (Ustrchr(keystring, '/') != 0) | |
84 | { | |
85 | *errmsg = string_sprintf("key for dsearch lookup contains a slash: %s", | |
86 | keystring); | |
87 | return DEFER; | |
88 | } | |
89 | ||
90 | if (!string_format(filename, sizeof(filename), "%s/%s", dirname, keystring)) | |
91 | { | |
92 | *errmsg = US"path name too long"; | |
93 | return DEFER; | |
94 | } | |
95 | ||
96 | if (Ustat(filename, &statbuf) >= 0) | |
97 | { | |
98 | *result = string_copy(keystring); | |
99 | return OK; | |
100 | } | |
101 | ||
102 | if (errno == ENOENT) return FAIL; | |
103 | ||
104 | save_errno = errno; | |
105 | *errmsg = string_sprintf("%s: stat failed", filename); | |
106 | errno = save_errno; | |
107 | return DEFER; | |
108 | } | |
109 | ||
110 | ||
111 | /************************************************* | |
112 | * Close entry point * | |
113 | *************************************************/ | |
114 | ||
115 | /* See local README for interface description */ | |
116 | ||
117 | void | |
118 | dsearch_close(void *handle) | |
119 | { | |
120 | handle = handle; /* Avoid compiler warning */ | |
121 | } | |
122 | ||
123 | /* End of lookups/dsearch.c */ |