Commit | Line | Data |
---|---|---|
0a49a7a4 | 1 | /* $Cambridge: exim/src/src/lookups/dsearch.c,v 1.6 2009/11/16 19:50:38 nm4 Exp $ */ |
0756eb3c PH |
2 | |
3 | /************************************************* | |
4 | * Exim - an Internet mail transport agent * | |
5 | *************************************************/ | |
6 | ||
0a49a7a4 | 7 | /* Copyright (c) University of Cambridge 1995 - 2009 */ |
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 | |
0f2cbd1b MH |
11 | been heavily reworked a lot for Exim 4 (and it now uses stat() (more precisely: |
12 | lstat()) rather than a directory scan). */ | |
0756eb3c PH |
13 | |
14 | ||
15 | #include "../exim.h" | |
16 | #include "lf_functions.h" | |
0756eb3c PH |
17 | |
18 | ||
19 | ||
20 | /************************************************* | |
21 | * Open entry point * | |
22 | *************************************************/ | |
23 | ||
24 | /* See local README for interface description. We open the directory to test | |
25 | whether it exists and whether it is searchable. However, we don't need to keep | |
0f2cbd1b | 26 | it open, because the "search" can be done by a call to lstat() rather than |
0756eb3c PH |
27 | actually scanning through the list of files. */ |
28 | ||
e6d225ae | 29 | static void * |
0756eb3c PH |
30 | dsearch_open(uschar *dirname, uschar **errmsg) |
31 | { | |
32 | DIR *dp = opendir(CS dirname); | |
33 | if (dp == NULL) | |
34 | { | |
35 | int save_errno = errno; | |
36 | *errmsg = string_open_failed(errno, "%s for directory search", dirname); | |
37 | errno = save_errno; | |
38 | return NULL; | |
39 | } | |
40 | closedir(dp); | |
41 | return (void *)(-1); | |
42 | } | |
43 | ||
44 | ||
45 | /************************************************* | |
46 | * Check entry point * | |
47 | *************************************************/ | |
48 | ||
49 | /* The handle will always be (void *)(-1), but don't try casting it to an | |
50 | integer as this gives warnings on 64-bit systems. */ | |
51 | ||
52 | BOOL | |
e6d225ae | 53 | static dsearch_check(void *handle, uschar *filename, int modemask, uid_t *owners, |
0756eb3c PH |
54 | gid_t *owngroups, uschar **errmsg) |
55 | { | |
56 | handle = handle; | |
57 | return lf_check_file(-1, filename, S_IFDIR, modemask, owners, owngroups, | |
58 | "dsearch", errmsg) == 0; | |
59 | } | |
60 | ||
61 | ||
62 | /************************************************* | |
63 | * Find entry point * | |
64 | *************************************************/ | |
65 | ||
0f2cbd1b | 66 | /* See local README for interface description. We use lstat() instead of |
0756eb3c PH |
67 | scanning the directory, as it is hopefully faster to let the OS do the scanning |
68 | for us. */ | |
69 | ||
70 | int | |
e6d225ae | 71 | static dsearch_find(void *handle, uschar *dirname, uschar *keystring, int length, |
0756eb3c PH |
72 | uschar **result, uschar **errmsg, BOOL *do_cache) |
73 | { | |
74 | struct stat statbuf; | |
75 | int save_errno; | |
76 | uschar filename[PATH_MAX]; | |
77 | ||
78 | handle = handle; /* Keep picky compilers happy */ | |
79 | length = length; | |
80 | do_cache = do_cache; | |
81 | ||
82 | if (Ustrchr(keystring, '/') != 0) | |
83 | { | |
84 | *errmsg = string_sprintf("key for dsearch lookup contains a slash: %s", | |
85 | keystring); | |
86 | return DEFER; | |
87 | } | |
88 | ||
89 | if (!string_format(filename, sizeof(filename), "%s/%s", dirname, keystring)) | |
90 | { | |
91 | *errmsg = US"path name too long"; | |
92 | return DEFER; | |
93 | } | |
94 | ||
0f2cbd1b | 95 | if (Ulstat(filename, &statbuf) >= 0) |
0756eb3c PH |
96 | { |
97 | *result = string_copy(keystring); | |
98 | return OK; | |
99 | } | |
100 | ||
101 | if (errno == ENOENT) return FAIL; | |
102 | ||
103 | save_errno = errno; | |
0f2cbd1b | 104 | *errmsg = string_sprintf("%s: lstat failed", filename); |
0756eb3c PH |
105 | errno = save_errno; |
106 | return DEFER; | |
107 | } | |
108 | ||
109 | ||
110 | /************************************************* | |
111 | * Close entry point * | |
112 | *************************************************/ | |
113 | ||
114 | /* See local README for interface description */ | |
115 | ||
116 | void | |
e6d225ae | 117 | static dsearch_close(void *handle) |
0756eb3c PH |
118 | { |
119 | handle = handle; /* Avoid compiler warning */ | |
120 | } | |
121 | ||
6545de78 PP |
122 | |
123 | /************************************************* | |
124 | * Version reporting entry point * | |
125 | *************************************************/ | |
126 | ||
127 | /* See local README for interface description. */ | |
128 | ||
129 | #include "../version.h" | |
130 | ||
131 | void | |
132 | dsearch_version_report(FILE *f) | |
133 | { | |
134 | #ifdef DYNLOOKUP | |
135 | fprintf(f, "Library version: dsearch: Exim version %s\n", EXIM_VERSION_STR); | |
136 | #endif | |
137 | } | |
138 | ||
139 | ||
e6d225ae DW |
140 | static lookup_info _lookup_info = { |
141 | US"dsearch", /* lookup name */ | |
142 | lookup_absfile, /* uses absolute file name */ | |
143 | dsearch_open, /* open function */ | |
144 | dsearch_check, /* check function */ | |
145 | dsearch_find, /* find function */ | |
146 | dsearch_close, /* close function */ | |
147 | NULL, /* no tidy function */ | |
6545de78 PP |
148 | NULL, /* no quoting function */ |
149 | dsearch_version_report /* version reporting */ | |
e6d225ae DW |
150 | }; |
151 | ||
152 | #ifdef DYNLOOKUP | |
153 | #define dsearch_lookup_module_info _lookup_module_info | |
154 | #endif | |
155 | ||
156 | static lookup_info *_lookup_list[] = { &_lookup_info }; | |
157 | lookup_module_info dsearch_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 }; | |
158 | ||
0756eb3c | 159 | /* End of lookups/dsearch.c */ |