~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/utils/net_cache.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Samba Unix/Linux SMB client library
 
3
   Distributed SMB/CIFS Server Management Utility
 
4
   Copyright (C) Rafal Szczesniak    2002
 
5
 
 
6
   This program is free software; you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 3 of the License, or
 
9
   (at your option) any later version.
 
10
 
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
#include "includes.h"
 
21
#include "net.h"
 
22
 
 
23
/**
 
24
 * @file net_cache.c
 
25
 * @brief This is part of the net tool which is basically command
 
26
 *        line wrapper for gencache.c functions (mainly for testing)
 
27
 *
 
28
 **/
 
29
 
 
30
 
 
31
/*
 
32
 * These routines are used via gencache_iterate() to display the cache's contents
 
33
 * (print_cache_entry) and to flush it (delete_cache_entry).
 
34
 * Both of them are defined by first arg of gencache_iterate() routine.
 
35
 */
 
36
static void print_cache_entry(const char* keystr, const char* datastr,
 
37
                              const time_t timeout, void* dptr)
 
38
{
 
39
        char *timeout_str;
 
40
        char *alloc_str = NULL;
 
41
        time_t now_t = time(NULL);
 
42
        struct tm timeout_tm, *now_tm;
 
43
        /* localtime returns statically allocated pointer, so timeout_tm
 
44
           has to be copied somewhere else */
 
45
 
 
46
        now_tm = localtime(&timeout);
 
47
        if (!now_tm) {
 
48
                return;
 
49
        }
 
50
        memcpy(&timeout_tm, now_tm, sizeof(struct tm));
 
51
        now_tm = localtime(&now_t);
 
52
        if (!now_tm) {
 
53
                return;
 
54
        }
 
55
 
 
56
        /* form up timeout string depending whether it's today's date or not */
 
57
        if (timeout_tm.tm_year != now_tm->tm_year ||
 
58
                        timeout_tm.tm_mon != now_tm->tm_mon ||
 
59
                        timeout_tm.tm_mday != now_tm->tm_mday) {
 
60
 
 
61
                timeout_str = asctime(&timeout_tm);
 
62
                if (!timeout_str) {
 
63
                        return;
 
64
                }
 
65
                timeout_str[strlen(timeout_str) - 1] = '\0';    /* remove tailing CR */
 
66
        } else {
 
67
                if (asprintf(&alloc_str, "%.2d:%.2d:%.2d", timeout_tm.tm_hour,
 
68
                         timeout_tm.tm_min, timeout_tm.tm_sec) == -1) {
 
69
                        return;
 
70
                }
 
71
                timeout_str = alloc_str;
 
72
        }
 
73
 
 
74
        d_printf("Key: %s\t Timeout: %s\t Value: %s  %s\n", keystr,
 
75
                 timeout_str, datastr, timeout > now_t ? "": "(expired)");
 
76
 
 
77
        SAFE_FREE(alloc_str);
 
78
}
 
79
 
 
80
static void delete_cache_entry(const char* keystr, const char* datastr,
 
81
                               const time_t timeout, void* dptr)
 
82
{
 
83
        if (!gencache_del(keystr))
 
84
                d_fprintf(stderr, "Couldn't delete entry! key = %s\n", keystr);
 
85
}
 
86
 
 
87
 
 
88
/**
 
89
 * Parse text representation of timeout value
 
90
 *
 
91
 * @param timeout_str string containing text representation of the timeout
 
92
 * @return numeric timeout of time_t type
 
93
 **/
 
94
static time_t parse_timeout(const char* timeout_str)
 
95
{
 
96
        char sign = '\0', *number = NULL, unit = '\0';
 
97
        int len, number_begin, number_end;
 
98
        time_t timeout;
 
99
 
 
100
        /* sign detection */
 
101
        if (timeout_str[0] == '!' || timeout_str[0] == '+') {
 
102
                sign = timeout_str[0];
 
103
                number_begin = 1;
 
104
        } else {
 
105
                number_begin = 0;
 
106
        }
 
107
 
 
108
        /* unit detection */
 
109
        len = strlen(timeout_str);
 
110
        switch (timeout_str[len - 1]) {
 
111
        case 's':
 
112
        case 'm':
 
113
        case 'h':
 
114
        case 'd':
 
115
        case 'w': unit = timeout_str[len - 1];
 
116
        }
 
117
 
 
118
        /* number detection */
 
119
        len = (sign) ? strlen(&timeout_str[number_begin]) : len;
 
120
        number_end = (unit) ? len - 1 : len;
 
121
        number = SMB_STRNDUP(&timeout_str[number_begin], number_end);
 
122
 
 
123
        /* calculate actual timeout value */
 
124
        timeout = (time_t)atoi(number);
 
125
 
 
126
        switch (unit) {
 
127
        case 'm': timeout *= 60; break;
 
128
        case 'h': timeout *= 60*60; break;
 
129
        case 'd': timeout *= 60*60*24; break;
 
130
        case 'w': timeout *= 60*60*24*7; break;  /* that's fair enough, I think :) */
 
131
        }
 
132
 
 
133
        switch (sign) {
 
134
        case '!': timeout = time(NULL) - timeout; break;
 
135
        case '+':
 
136
        default:  timeout += time(NULL); break;
 
137
        }
 
138
 
 
139
        if (number) SAFE_FREE(number);
 
140
        return timeout;
 
141
}
 
142
 
 
143
 
 
144
/**
 
145
 * Add an entry to the cache. If it does exist, then set it.
 
146
 *
 
147
 * @param c     A net_context structure
 
148
 * @param argv key, value and timeout are passed in command line
 
149
 * @return 0 on success, otherwise failure
 
150
 **/
 
151
static int net_cache_add(struct net_context *c, int argc, const char **argv)
 
152
{
 
153
        const char *keystr, *datastr, *timeout_str;
 
154
        time_t timeout;
 
155
 
 
156
        if (argc < 3 || c->display_usage) {
 
157
                d_printf("\nUsage: net cache add <key string> <data string> <timeout>\n");
 
158
                return -1;
 
159
        }
 
160
 
 
161
        keystr = argv[0];
 
162
        datastr = argv[1];
 
163
        timeout_str = argv[2];
 
164
 
 
165
        /* parse timeout given in command line */
 
166
        timeout = parse_timeout(timeout_str);
 
167
        if (!timeout) {
 
168
                d_fprintf(stderr, "Invalid timeout argument.\n");
 
169
                return -1;
 
170
        }
 
171
 
 
172
        if (gencache_set(keystr, datastr, timeout)) {
 
173
                d_printf("New cache entry stored successfully.\n");
 
174
                gencache_shutdown();
 
175
                return 0;
 
176
        }
 
177
 
 
178
        d_fprintf(stderr, "Entry couldn't be added. Perhaps there's already such a key.\n");
 
179
        gencache_shutdown();
 
180
        return -1;
 
181
}
 
182
 
 
183
/**
 
184
 * Delete an entry in the cache
 
185
 *
 
186
 * @param c     A net_context structure
 
187
 * @param argv key to delete an entry of
 
188
 * @return 0 on success, otherwise failure
 
189
 **/
 
190
static int net_cache_del(struct net_context *c, int argc, const char **argv)
 
191
{
 
192
        const char *keystr = argv[0];
 
193
 
 
194
        if (argc < 1 || c->display_usage) {
 
195
                d_printf("\nUsage: net cache del <key string>\n");
 
196
                return -1;
 
197
        }
 
198
 
 
199
        if(gencache_del(keystr)) {
 
200
                d_printf("Entry deleted.\n");
 
201
                return 0;
 
202
        }
 
203
 
 
204
        d_fprintf(stderr, "Couldn't delete specified entry\n");
 
205
        return -1;
 
206
}
 
207
 
 
208
 
 
209
/**
 
210
 * Get and display an entry from the cache
 
211
 *
 
212
 * @param c     A net_context structure
 
213
 * @param argv key to search an entry of
 
214
 * @return 0 on success, otherwise failure
 
215
 **/
 
216
static int net_cache_get(struct net_context *c, int argc, const char **argv)
 
217
{
 
218
        const char* keystr = argv[0];
 
219
        char* valuestr = NULL;
 
220
        time_t timeout;
 
221
 
 
222
        if (argc < 1 || c->display_usage) {
 
223
                d_printf("\nUsage: net cache get <key>\n");
 
224
                return -1;
 
225
        }
 
226
 
 
227
        if (gencache_get(keystr, &valuestr, &timeout)) {
 
228
                print_cache_entry(keystr, valuestr, timeout, NULL);
 
229
                SAFE_FREE(valuestr);
 
230
                return 0;
 
231
        }
 
232
 
 
233
        d_fprintf(stderr, "Failed to find entry\n");
 
234
        return -1;
 
235
}
 
236
 
 
237
 
 
238
/**
 
239
 * Search an entry/entries in the cache
 
240
 *
 
241
 * @param c     A net_context structure
 
242
 * @param argv key pattern to match the entries to
 
243
 * @return 0 on success, otherwise failure
 
244
 **/
 
245
static int net_cache_search(struct net_context *c, int argc, const char **argv)
 
246
{
 
247
        const char* pattern;
 
248
 
 
249
        if (argc < 1 || c->display_usage) {
 
250
                d_printf("Usage: net cache search <pattern>\n");
 
251
                return -1;
 
252
        }
 
253
 
 
254
        pattern = argv[0];
 
255
        gencache_iterate(print_cache_entry, NULL, pattern);
 
256
        return 0;
 
257
}
 
258
 
 
259
 
 
260
/**
 
261
 * List the contents of the cache
 
262
 *
 
263
 * @param c     A net_context structure
 
264
 * @param argv ignored in this functionailty
 
265
 * @return always returns 0
 
266
 **/
 
267
static int net_cache_list(struct net_context *c, int argc, const char **argv)
 
268
{
 
269
        const char* pattern = "*";
 
270
 
 
271
        if (c->display_usage) {
 
272
                d_printf("Usage:\n"
 
273
                         "net cache list\n"
 
274
                         "    List all cache entries.\n");
 
275
                return 0;
 
276
        }
 
277
        gencache_iterate(print_cache_entry, NULL, pattern);
 
278
        gencache_shutdown();
 
279
        return 0;
 
280
}
 
281
 
 
282
 
 
283
/**
 
284
 * Flush the whole cache
 
285
 *
 
286
 * @param c     A net_context structure
 
287
 * @param argv ignored in this functionality
 
288
 * @return always returns 0
 
289
 **/
 
290
static int net_cache_flush(struct net_context *c, int argc, const char **argv)
 
291
{
 
292
        const char* pattern = "*";
 
293
        if (c->display_usage) {
 
294
                d_printf("Usage:\n"
 
295
                         "net cache flush\n"
 
296
                         "    Delete all cache entries.\n");
 
297
                return 0;
 
298
        }
 
299
        gencache_iterate(delete_cache_entry, NULL, pattern);
 
300
        gencache_shutdown();
 
301
        return 0;
 
302
}
 
303
 
 
304
/**
 
305
 * Entry point to 'net cache' subfunctionality
 
306
 *
 
307
 * @param c     A net_context structure
 
308
 * @param argv arguments passed to further called functions
 
309
 * @return whatever further functions return
 
310
 **/
 
311
int net_cache(struct net_context *c, int argc, const char **argv)
 
312
{
 
313
        struct functable func[] = {
 
314
                {
 
315
                        "add",
 
316
                        net_cache_add,
 
317
                        NET_TRANSPORT_LOCAL,
 
318
                        "Add new cache entry",
 
319
                        "net cache add <key string> <data string> <timeout>\n"
 
320
                        "  Add new cache entry.\n"
 
321
                        "    key string\tKey string to add cache data under.\n"
 
322
                        "    data string\tData to store under given key.\n"
 
323
                        "    timeout\tTimeout for cache data."
 
324
                },
 
325
                {
 
326
                        "del",
 
327
                        net_cache_del,
 
328
                        NET_TRANSPORT_LOCAL,
 
329
                        "Delete existing cache entry by key",
 
330
                        "net cache del <key string>\n"
 
331
                        "  Delete existing cache entry by key.\n"
 
332
                        "    key string\tKey string to delete."
 
333
                },
 
334
                {
 
335
                        "get",
 
336
                        net_cache_get,
 
337
                        NET_TRANSPORT_LOCAL,
 
338
                        "Get cache entry by key",
 
339
                        "net cache get <key string>\n"
 
340
                        "  Get cache entry by key.\n"
 
341
                        "    key string\tKey string to look up cache entry for."
 
342
 
 
343
                },
 
344
                {
 
345
                        "search",
 
346
                        net_cache_search,
 
347
                        NET_TRANSPORT_LOCAL,
 
348
                        "Search entry by pattern",
 
349
                        "net cache search <pattern>\n"
 
350
                        "  Search entry by pattern.\n"
 
351
                        "    pattern\tPattern to search for in cache."
 
352
                },
 
353
                {
 
354
                        "list",
 
355
                        net_cache_list,
 
356
                        NET_TRANSPORT_LOCAL,
 
357
                        "List all cache entries",
 
358
                        "net cache list\n"
 
359
                        "  List all cache entries"
 
360
                },
 
361
                {
 
362
                        "flush",
 
363
                        net_cache_flush,
 
364
                        NET_TRANSPORT_LOCAL,
 
365
                        "Delete all cache entries",
 
366
                        "net cache flush\n"
 
367
                        "  Delete all cache entries"
 
368
                },
 
369
                {NULL, NULL, 0, NULL, NULL}
 
370
        };
 
371
 
 
372
        return net_run_function(c, argc, argv, "net cache", func);
 
373
}