4 Copyright (C) Simo Sorce 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Component: ldb timestamps module
30 * Description: add object timestamping functionality
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
41 const char *error_string;
44 static int timestamps_search(struct ldb_module *module, const char *base,
45 enum ldb_scope scope, const char *expression,
46 const char * const *attrs, struct ldb_message ***res)
48 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search\n");
49 return ldb_next_search(module, base, scope, expression, attrs, res);
52 static int timestamps_search_free(struct ldb_module *module, struct ldb_message **res)
54 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search_free\n");
55 return ldb_next_search_free(module, res);
58 static int add_time_element(struct ldb_module *module, struct ldb_message *msg,
59 const char *attr_name, const char *time_string, unsigned int flags)
61 struct ldb_val *values;
65 for (i = 0; i < msg->num_elements; i++) {
66 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
71 msg->elements = talloc_realloc(msg, msg->elements,
72 struct ldb_message_element, msg->num_elements + 1);
73 name = talloc_strdup(msg->elements, attr_name);
74 timestr = talloc_strdup(msg->elements, time_string);
75 values = talloc(msg->elements, struct ldb_val);
76 if (!msg->elements || !name || !timestr || !values) {
80 msg->elements[msg->num_elements].name = name;
81 msg->elements[msg->num_elements].flags = flags;
82 msg->elements[msg->num_elements].num_values = 1;
83 msg->elements[msg->num_elements].values = values;
84 msg->elements[msg->num_elements].values[0].data = timestr;
85 msg->elements[msg->num_elements].values[0].length = strlen(timestr);
87 msg->num_elements += 1;
92 /* add_record: add crateTimestamp/modifyTimestamp attributes */
93 static int timestamps_add_record(struct ldb_module *module, const struct ldb_message *msg)
95 struct ldb_message *msg2 = NULL;
101 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_add_record\n");
103 if (msg->dn[0] == '@') { /* do not manipulate our control entries */
104 return ldb_next_add_record(module, msg);
107 timeval = time(NULL);
108 tm = gmtime(&timeval);
113 msg2 = talloc(module, struct ldb_message);
118 /* formatted like: 20040408072012.0Z */
119 timestr = talloc_asprintf(msg2, "%04u%02u%02u%02u%02u%02u.0Z",
120 tm->tm_year+1900, tm->tm_mon+1,
121 tm->tm_mday, tm->tm_hour, tm->tm_min,
128 msg2->num_elements = msg->num_elements;
129 msg2->private_data = msg->private_data;
130 msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements);
131 for (i = 0; i < msg2->num_elements; i++) {
132 msg2->elements[i] = msg->elements[i];
135 add_time_element(module, msg2, "createTimestamp", timestr, LDB_FLAG_MOD_ADD);
136 add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD);
137 add_time_element(module, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD);
138 add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD);
141 ret = ldb_next_add_record(module, msg2);
144 ret = ldb_next_add_record(module, msg);
150 /* modify_record: change modifyTimestamp as well */
151 static int timestamps_modify_record(struct ldb_module *module, const struct ldb_message *msg)
153 struct ldb_message *msg2 = NULL;
159 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_modify_record\n");
161 if (msg->dn[0] == '@') { /* do not manipulate our control entries */
162 return ldb_next_modify_record(module, msg);
165 timeval = time(NULL);
166 tm = gmtime(&timeval);
171 msg2 = talloc(module, struct ldb_message);
176 /* formatted like: 20040408072012.0Z */
177 timestr = talloc_asprintf(msg2,
178 "%04u%02u%02u%02u%02u%02u.0Z",
179 tm->tm_year+1900, tm->tm_mon+1,
180 tm->tm_mday, tm->tm_hour, tm->tm_min,
187 msg2->num_elements = msg->num_elements;
188 msg2->private_data = msg->private_data;
189 msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements);
190 for (i = 0; i < msg2->num_elements; i++) {
191 msg2->elements[i] = msg->elements[i];
194 add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE);
195 add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE);
198 ret = ldb_next_modify_record(module, msg2);
201 ret = ldb_next_modify_record(module, msg);
207 static int timestamps_delete_record(struct ldb_module *module, const char *dn)
209 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_delete_record\n");
210 return ldb_next_delete_record(module, dn);
213 static int timestamps_rename_record(struct ldb_module *module, const char *olddn, const char *newdn)
215 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_rename_record\n");
216 return ldb_next_rename_record(module, olddn, newdn);
219 static int timestamps_lock(struct ldb_module *module, const char *lockname)
221 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_lock\n");
222 return ldb_next_named_lock(module, lockname);
225 static int timestamps_unlock(struct ldb_module *module, const char *lockname)
227 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_unlock\n");
228 return ldb_next_named_unlock(module, lockname);
231 /* return extended error information */
232 static const char *timestamps_errstring(struct ldb_module *module)
234 struct private_data *data = (struct private_data *)module->private_data;
236 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_errstring\n");
237 if (data->error_string) {
240 error = data->error_string;
241 data->error_string = NULL;
245 return ldb_next_errstring(module);
248 static int timestamps_destructor(void *module_ctx)
250 struct ldb_module *ctx = module_ctx;
251 /* put your clean-up functions here */
255 static const struct ldb_module_ops timestamps_ops = {
258 timestamps_search_free,
259 timestamps_add_record,
260 timestamps_modify_record,
261 timestamps_delete_record,
262 timestamps_rename_record,
269 /* the init function */
270 #ifdef HAVE_DLOPEN_DISABLED
271 struct ldb_module *init_module(struct ldb_context *ldb, const char *options[])
273 struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *options[])
276 struct ldb_module *ctx;
277 struct private_data *data;
279 ctx = talloc(ldb, struct ldb_module);
283 data = talloc(ctx, struct private_data);
289 data->error_string = NULL;
290 ctx->private_data = data;
292 ctx->prev = ctx->next = NULL;
293 ctx->ops = ×tamps_ops;
295 talloc_set_destructor (ctx, timestamps_destructor);