• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source3/utils/
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 */
36static 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
80static 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"),
85			  keystr);
86}
87
88
89/**
90 * Parse text representation of timeout value
91 *
92 * @param timeout_str string containing text representation of the timeout
93 * @return numeric timeout of time_t type
94 **/
95static time_t parse_timeout(const char* timeout_str)
96{
97	char sign = '\0', *number = NULL, unit = '\0';
98	int len, number_begin, number_end;
99	time_t timeout;
100
101	/* sign detection */
102	if (timeout_str[0] == '!' || timeout_str[0] == '+') {
103		sign = timeout_str[0];
104		number_begin = 1;
105	} else {
106		number_begin = 0;
107	}
108
109	/* unit detection */
110	len = strlen(timeout_str);
111	switch (timeout_str[len - 1]) {
112	case 's':
113	case 'm':
114	case 'h':
115	case 'd':
116	case 'w': unit = timeout_str[len - 1];
117	}
118
119	/* number detection */
120	len = (sign) ? strlen(&timeout_str[number_begin]) : len;
121	number_end = (unit) ? len - 1 : len;
122	number = SMB_STRNDUP(&timeout_str[number_begin], number_end);
123
124	/* calculate actual timeout value */
125	timeout = (time_t)atoi(number);
126
127	switch (unit) {
128	case 'm': timeout *= 60; break;
129	case 'h': timeout *= 60*60; break;
130	case 'd': timeout *= 60*60*24; break;
131	case 'w': timeout *= 60*60*24*7; break;  /* that's fair enough, I think :) */
132	}
133
134	switch (sign) {
135	case '!': timeout = time(NULL) - timeout; break;
136	case '+':
137	default:  timeout += time(NULL); break;
138	}
139
140	if (number) SAFE_FREE(number);
141	return timeout;
142}
143
144
145/**
146 * Add an entry to the cache. If it does exist, then set it.
147 *
148 * @param c	A net_context structure
149 * @param argv key, value and timeout are passed in command line
150 * @return 0 on success, otherwise failure
151 **/
152static int net_cache_add(struct net_context *c, int argc, const char **argv)
153{
154	const char *keystr, *datastr, *timeout_str;
155	time_t timeout;
156
157	if (argc < 3 || c->display_usage) {
158		d_printf("%s\n%s",
159			 _("Usage:"),
160			 _("net cache add <key string> <data string> "
161			   "<timeout>\n"));
162		return -1;
163	}
164
165	keystr = argv[0];
166	datastr = argv[1];
167	timeout_str = argv[2];
168
169	/* parse timeout given in command line */
170	timeout = parse_timeout(timeout_str);
171	if (!timeout) {
172		d_fprintf(stderr, _("Invalid timeout argument.\n"));
173		return -1;
174	}
175
176	if (gencache_set(keystr, datastr, timeout)) {
177		d_printf(_("New cache entry stored successfully.\n"));
178		return 0;
179	}
180
181	d_fprintf(stderr, _("Entry couldn't be added. Perhaps there's already such a key.\n"));
182	return -1;
183}
184
185/**
186 * Delete an entry in the cache
187 *
188 * @param c	A net_context structure
189 * @param argv key to delete an entry of
190 * @return 0 on success, otherwise failure
191 **/
192static int net_cache_del(struct net_context *c, int argc, const char **argv)
193{
194	const char *keystr = argv[0];
195
196	if (argc < 1 || c->display_usage) {
197		d_printf("%s\n%s",
198			 _("Usage:"),
199			 _(" net cache del <key string>\n"));
200		return -1;
201	}
202
203	if(gencache_del(keystr)) {
204		d_printf(_("Entry deleted.\n"));
205		return 0;
206	}
207
208	d_fprintf(stderr, _("Couldn't delete specified entry\n"));
209	return -1;
210}
211
212
213/**
214 * Get and display an entry from the cache
215 *
216 * @param c	A net_context structure
217 * @param argv key to search an entry of
218 * @return 0 on success, otherwise failure
219 **/
220static int net_cache_get(struct net_context *c, int argc, const char **argv)
221{
222	const char* keystr = argv[0];
223	char* valuestr = NULL;
224	time_t timeout;
225
226	if (argc < 1 || c->display_usage) {
227		d_printf("%s\n%s",
228			 _("Usage:"),
229			 _(" net cache get <key>\n"));
230		return -1;
231	}
232
233	if (gencache_get(keystr, &valuestr, &timeout)) {
234		print_cache_entry(keystr, valuestr, timeout, NULL);
235		SAFE_FREE(valuestr);
236		return 0;
237	}
238
239	d_fprintf(stderr, _("Failed to find entry\n"));
240	return -1;
241}
242
243
244/**
245 * Search an entry/entries in the cache
246 *
247 * @param c	A net_context structure
248 * @param argv key pattern to match the entries to
249 * @return 0 on success, otherwise failure
250 **/
251static int net_cache_search(struct net_context *c, int argc, const char **argv)
252{
253	const char* pattern;
254
255	if (argc < 1 || c->display_usage) {
256		d_printf("%s\n%s",
257			 _("Usage:"),
258			 _(" net cache search <pattern>\n"));
259		return -1;
260	}
261
262	pattern = argv[0];
263	gencache_iterate(print_cache_entry, NULL, pattern);
264	return 0;
265}
266
267
268/**
269 * List the contents of the cache
270 *
271 * @param c	A net_context structure
272 * @param argv ignored in this functionailty
273 * @return always returns 0
274 **/
275static int net_cache_list(struct net_context *c, int argc, const char **argv)
276{
277	const char* pattern = "*";
278
279	if (c->display_usage) {
280		d_printf(  "%s\n"
281			   "net cache list\n"
282			   "    %s\n",
283			 _("Usage:"),
284			 _("List all cache entries."));
285		return 0;
286	}
287	gencache_iterate(print_cache_entry, NULL, pattern);
288	return 0;
289}
290
291
292/**
293 * Flush the whole cache
294 *
295 * @param c	A net_context structure
296 * @param argv ignored in this functionality
297 * @return always returns 0
298 **/
299static int net_cache_flush(struct net_context *c, int argc, const char **argv)
300{
301	const char* pattern = "*";
302	if (c->display_usage) {
303		d_printf(  "%s\n"
304			   "net cache flush\n"
305			   "    %s",
306			 _("Usage:"),
307			 _("Delete all cache entries."));
308		return 0;
309	}
310	gencache_iterate(delete_cache_entry, NULL, pattern);
311	return 0;
312}
313
314static int net_cache_stabilize(struct net_context *c, int argc,
315			       const char **argv)
316{
317	if (c->display_usage) {
318		d_printf(  "%s\n"
319			   "net cache stabilize\n"
320			   "    %s\n",
321			 _("Usage:"),
322			 _("Move transient cache content to stable storage"));
323		return 0;
324	}
325
326	if (!gencache_stabilize()) {
327		return -1;
328	}
329	return 0;
330}
331/**
332 * Entry point to 'net cache' subfunctionality
333 *
334 * @param c	A net_context structure
335 * @param argv arguments passed to further called functions
336 * @return whatever further functions return
337 **/
338int net_cache(struct net_context *c, int argc, const char **argv)
339{
340	struct functable func[] = {
341		{
342			"add",
343			net_cache_add,
344			NET_TRANSPORT_LOCAL,
345			N_("Add new cache entry"),
346			N_("net cache add <key string> <data string> <timeout>\n"
347			   "  Add new cache entry.\n"
348			   "    key string\tKey string to add cache data under.\n"
349			   "    data string\tData to store under given key.\n"
350			   "    timeout\tTimeout for cache data.")
351		},
352		{
353			"del",
354			net_cache_del,
355			NET_TRANSPORT_LOCAL,
356			N_("Delete existing cache entry by key"),
357			N_("net cache del <key string>\n"
358			   "  Delete existing cache entry by key.\n"
359			   "    key string\tKey string to delete.")
360		},
361		{
362			"get",
363			net_cache_get,
364			NET_TRANSPORT_LOCAL,
365			N_("Get cache entry by key"),
366			N_("net cache get <key string>\n"
367			   "  Get cache entry by key.\n"
368			   "    key string\tKey string to look up cache entry for.")
369
370		},
371		{
372			"search",
373			net_cache_search,
374			NET_TRANSPORT_LOCAL,
375			N_("Search entry by pattern"),
376			N_("net cache search <pattern>\n"
377			   "  Search entry by pattern.\n"
378			   "    pattern\tPattern to search for in cache.")
379		},
380		{
381			"list",
382			net_cache_list,
383			NET_TRANSPORT_LOCAL,
384			N_("List all cache entries"),
385			N_("net cache list\n"
386			   "  List all cache entries")
387		},
388		{
389			"flush",
390			net_cache_flush,
391			NET_TRANSPORT_LOCAL,
392			N_("Delete all cache entries"),
393			N_("net cache flush\n"
394			   "  Delete all cache entries")
395		},
396		{
397			"stabilize",
398			net_cache_stabilize,
399			NET_TRANSPORT_LOCAL,
400			N_("Move transient cache content to stable storage"),
401			N_("net cache stabilize\n"
402			   "  Move transient cache content to stable storage")
403		},
404		{NULL, NULL, 0, NULL, NULL}
405	};
406
407	return net_run_function(c, argc, argv, "net cache", func);
408}
409