1 /**
2 * Copyright (C) 2008 Happy Fish / YuQing
3 *
4 * FastDFS may be copied only under the terms of the GNU General
5 * Public License V3, which may be found in the FastDFS source kit.
6 * Please visit the FastDFS Home Page http://www.fastken.com/ for more detail.
7 **/
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include "fdfs_client.h"
17 #include "fdfs_global.h"
18 #include "fastcommon/base64.h"
19 #include "fastcommon/sockopt.h"
20 #include "fastcommon/logger.h"
21 #include "fdfs_http_shared.h"
22 
writeToFileCallback(void * arg,const int64_t file_size,const char * data,const int current_size)23 int writeToFileCallback(void *arg, const int64_t file_size, const char *data, \
24                 const int current_size)
25 {
26 	if (arg == NULL)
27 	{
28 		return EINVAL;
29 	}
30 
31 	if (fwrite(data, current_size, 1, (FILE *)arg) != 1)
32 	{
33 		return errno != 0 ? errno : EIO;
34 	}
35 
36 	return 0;
37 }
38 
uploadFileCallback(void * arg,const int64_t file_size,int sock)39 int uploadFileCallback(void *arg, const int64_t file_size, int sock)
40 {
41 	int64_t total_send_bytes;
42 	char *filename;
43 
44 	if (arg == NULL)
45 	{
46 		return EINVAL;
47 	}
48 
49 	filename = (char *)arg;
50 	return tcpsendfile(sock, filename, file_size, \
51 		g_fdfs_network_timeout, &total_send_bytes);
52 }
53 
main(int argc,char * argv[])54 int main(int argc, char *argv[])
55 {
56 	char *conf_filename;
57 	char *local_filename;
58 	ConnectionInfo *pTrackerServer;
59 	ConnectionInfo *pStorageServer;
60 	int result;
61 	ConnectionInfo storageServer;
62 	char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
63 	char remote_filename[256];
64 	char master_filename[256];
65 	FDFSMetaData meta_list[32];
66 	int meta_count;
67 	int i;
68 	FDFSMetaData *pMetaList;
69 	char token[32 + 1];
70 	char file_id[128];
71 	char file_url[256];
72 	char szDatetime[20];
73 	char szPortPart[16];
74 	int url_len;
75 	time_t ts;
76         char *file_buff;
77 	int64_t file_size;
78 	char *operation;
79 	char *meta_buff;
80 	int store_path_index;
81 	FDFSFileInfo file_info;
82 
83 	printf("This is FastDFS client test program v%d.%02d\n" \
84 "\nCopyright (C) 2008, Happy Fish / YuQing\n" \
85 "\nFastDFS may be copied only under the terms of the GNU General\n" \
86 "Public License V3, which may be found in the FastDFS source kit.\n" \
87 "Please visit the FastDFS Home Page http://www.fastken.com/ \n" \
88 "for more detail.\n\n" \
89 , g_fdfs_version.major, g_fdfs_version.minor);
90 
91 	if (argc < 3)
92 	{
93 		printf("Usage: %s <config_file> <operation>\n" \
94 			"\toperation: upload, download, getmeta, setmeta, " \
95 			"delete and query_servers\n", argv[0]);
96 		return 1;
97 	}
98 
99 	log_init();
100 	g_log_context.log_level = LOG_DEBUG;
101 
102 	conf_filename = argv[1];
103 	operation = argv[2];
104 	if ((result=fdfs_client_init(conf_filename)) != 0)
105 	{
106 		return result;
107 	}
108 
109 	pTrackerServer = tracker_get_connection();
110 	if (pTrackerServer == NULL)
111 	{
112 		fdfs_client_destroy();
113 		return errno != 0 ? errno : ECONNREFUSED;
114 	}
115 
116 	pStorageServer = NULL;
117 	*group_name = '\0';
118 	local_filename = NULL;
119 	if (strcmp(operation, "upload") == 0)
120 	{
121 		int upload_type;
122 		char *prefix_name;
123 		const char *file_ext_name;
124 		char slave_filename[256];
125 		int slave_filename_len;
126 
127 		if (argc < 4)
128 		{
129 			printf("Usage: %s <config_file> upload " \
130 				"<local_filename> [FILE | BUFF | CALLBACK] \n",\
131 				argv[0]);
132 			fdfs_client_destroy();
133 			return EINVAL;
134 		}
135 
136 		local_filename = argv[3];
137 		if (argc == 4)
138 		{
139 			upload_type = FDFS_UPLOAD_BY_FILE;
140 		}
141 		else
142 		{
143 			if (strcmp(argv[4], "BUFF") == 0)
144 			{
145 				upload_type = FDFS_UPLOAD_BY_BUFF;
146 			}
147 			else if (strcmp(argv[4], "CALLBACK") == 0)
148 			{
149 				upload_type = FDFS_UPLOAD_BY_CALLBACK;
150 			}
151 			else
152 			{
153 				upload_type = FDFS_UPLOAD_BY_FILE;
154 			}
155 		}
156 
157 		store_path_index = 0;
158 
159 		{
160 		ConnectionInfo storageServers[FDFS_MAX_SERVERS_EACH_GROUP];
161 		ConnectionInfo *pServer;
162 		ConnectionInfo *pServerEnd;
163 		int storage_count;
164 
165 		if ((result=tracker_query_storage_store_list_without_group( \
166 			pTrackerServer, storageServers, \
167 			FDFS_MAX_SERVERS_EACH_GROUP, &storage_count, \
168 			group_name, &store_path_index)) == 0)
169 		{
170 			printf("tracker_query_storage_store_list_without_group: \n");
171 			pServerEnd = storageServers + storage_count;
172 			for (pServer=storageServers; pServer<pServerEnd; pServer++)
173 			{
174 				printf("\tserver %d. group_name=%s, " \
175 				       "ip_addr=%s, port=%d\n", \
176 					(int)(pServer - storageServers) + 1, \
177 					group_name, pServer->ip_addr, pServer->port);
178 			}
179 			printf("\n");
180 		}
181 		}
182 
183 		if ((result=tracker_query_storage_store(pTrackerServer, \
184 		                &storageServer, group_name, &store_path_index)) != 0)
185 		{
186 			fdfs_client_destroy();
187 			printf("tracker_query_storage fail, " \
188 				"error no: %d, error info: %s\n", \
189 				result, STRERROR(result));
190 			return result;
191 		}
192 
193 		printf("group_name=%s, ip_addr=%s, port=%d\n", \
194 			group_name, storageServer.ip_addr, \
195 			storageServer.port);
196 
197 		if ((pStorageServer=tracker_make_connection(&storageServer, \
198 			&result)) == NULL)
199 		{
200 			fdfs_client_destroy();
201 			return result;
202 		}
203 
204 		memset(&meta_list, 0, sizeof(meta_list));
205 		meta_count = 0;
206 		strcpy(meta_list[meta_count].name, "ext_name");
207 		strcpy(meta_list[meta_count].value, "jpg");
208 		meta_count++;
209 		strcpy(meta_list[meta_count].name, "width");
210 		strcpy(meta_list[meta_count].value, "160");
211 		meta_count++;
212 		strcpy(meta_list[meta_count].name, "height");
213 		strcpy(meta_list[meta_count].value, "80");
214 		meta_count++;
215 		strcpy(meta_list[meta_count].name, "file_size");
216 		strcpy(meta_list[meta_count].value, "115120");
217 		meta_count++;
218 
219 		file_ext_name = fdfs_get_file_ext_name(local_filename);
220 		*group_name = '\0';
221 
222 		if (upload_type == FDFS_UPLOAD_BY_FILE)
223 		{
224 			result = storage_upload_by_filename(pTrackerServer, \
225 				pStorageServer, store_path_index, \
226 				local_filename, file_ext_name, \
227 				meta_list, meta_count, \
228 				group_name, remote_filename);
229 
230 			printf("storage_upload_by_filename\n");
231 		}
232 		else if (upload_type == FDFS_UPLOAD_BY_BUFF)
233 		{
234 			char *file_content;
235 			if ((result=getFileContent(local_filename, \
236 					&file_content, &file_size)) == 0)
237 			{
238 			result = storage_upload_by_filebuff(pTrackerServer, \
239 				pStorageServer, store_path_index, \
240 				file_content, file_size, file_ext_name, \
241 				meta_list, meta_count, \
242 				group_name, remote_filename);
243 			free(file_content);
244 			}
245 
246 			printf("storage_upload_by_filebuff\n");
247 		}
248 		else
249 		{
250 			struct stat stat_buf;
251 
252 			if (stat(local_filename, &stat_buf) == 0 && \
253 				S_ISREG(stat_buf.st_mode))
254 			{
255 			file_size = stat_buf.st_size;
256 			result = storage_upload_by_callback(pTrackerServer, \
257 				pStorageServer, store_path_index, \
258 				uploadFileCallback, local_filename, \
259 				file_size, file_ext_name, \
260 				meta_list, meta_count, \
261 				group_name, remote_filename);
262 			}
263 
264 			printf("storage_upload_by_callback\n");
265 		}
266 
267 		if (result != 0)
268 		{
269 			printf("upload file fail, " \
270 				"error no: %d, error info: %s\n", \
271 				result, STRERROR(result));
272 			tracker_close_connection_ex(pStorageServer, true);
273 			fdfs_client_destroy();
274 			return result;
275 		}
276 
277 		if (g_tracker_server_http_port == 80)
278 		{
279 			*szPortPart = '\0';
280 		}
281 		else
282 		{
283 			sprintf(szPortPart, ":%d", g_tracker_server_http_port);
284 		}
285 
286 		sprintf(file_id, "%s/%s", group_name, remote_filename);
287 		url_len = sprintf(file_url, "http://%s%s/%s", \
288 				pStorageServer->ip_addr, szPortPart, file_id);
289 		if (g_anti_steal_token)
290 		{
291 			ts = time(NULL);
292 			fdfs_http_gen_token(&g_anti_steal_secret_key, file_id, \
293                 		ts, token);
294 			sprintf(file_url + url_len, "?token=%s&ts=%d", \
295 				token, (int)ts);
296 		}
297 
298 		printf("group_name=%s, remote_filename=%s\n", \
299 			group_name, remote_filename);
300 
301 		fdfs_get_file_info(group_name, remote_filename, &file_info);
302 		printf("source ip address: %s\n", file_info.source_ip_addr);
303 		printf("file timestamp=%s\n", formatDatetime(
304 			file_info.create_timestamp, "%Y-%m-%d %H:%M:%S", \
305 			szDatetime, sizeof(szDatetime)));
306 		printf("file size=%"PRId64"\n", file_info.file_size);
307 		printf("file crc32=%u\n", file_info.crc32);
308 		printf("example file url: %s\n", file_url);
309 
310 		strcpy(master_filename, remote_filename);
311 		*remote_filename = '\0';
312 		if (upload_type == FDFS_UPLOAD_BY_FILE)
313 		{
314 			prefix_name = "_big";
315 			result = storage_upload_slave_by_filename(pTrackerServer,
316 				NULL, local_filename, master_filename, \
317 				prefix_name, file_ext_name, \
318 				meta_list, meta_count, \
319 				group_name, remote_filename);
320 
321 			printf("storage_upload_slave_by_filename\n");
322 		}
323 		else if (upload_type == FDFS_UPLOAD_BY_BUFF)
324 		{
325 			char *file_content;
326 			prefix_name = "1024x1024";
327 			if ((result=getFileContent(local_filename, \
328 					&file_content, &file_size)) == 0)
329 			{
330 			result = storage_upload_slave_by_filebuff(pTrackerServer, \
331 				NULL, file_content, file_size, master_filename,
332 				prefix_name, file_ext_name, \
333 				meta_list, meta_count, \
334 				group_name, remote_filename);
335 			free(file_content);
336 			}
337 
338 			printf("storage_upload_slave_by_filebuff\n");
339 		}
340 		else
341 		{
342 			struct stat stat_buf;
343 
344 			prefix_name = "-small";
345 			if (stat(local_filename, &stat_buf) == 0 && \
346 				S_ISREG(stat_buf.st_mode))
347 			{
348 			file_size = stat_buf.st_size;
349 			result = storage_upload_slave_by_callback(pTrackerServer, \
350 				NULL, uploadFileCallback, local_filename, \
351 				file_size, master_filename, prefix_name, \
352 				file_ext_name, meta_list, meta_count, \
353 				group_name, remote_filename);
354 			}
355 
356 			printf("storage_upload_slave_by_callback\n");
357 		}
358 
359 		if (result != 0)
360 		{
361 			printf("upload slave file fail, " \
362 				"error no: %d, error info: %s\n", \
363 				result, STRERROR(result));
364 			tracker_close_connection_ex(pStorageServer, true);
365 			fdfs_client_destroy();
366 			return result;
367 		}
368 
369 		if (g_tracker_server_http_port == 80)
370 		{
371 			*szPortPart = '\0';
372 		}
373 		else
374 		{
375 			sprintf(szPortPart, ":%d", g_tracker_server_http_port);
376 		}
377 
378 		sprintf(file_id, "%s/%s", group_name, remote_filename);
379 		url_len = sprintf(file_url, "http://%s%s/%s", \
380 				pStorageServer->ip_addr, szPortPart, file_id);
381 		if (g_anti_steal_token)
382 		{
383 			ts = time(NULL);
384 			fdfs_http_gen_token(&g_anti_steal_secret_key, file_id, \
385                 		ts, token);
386 			sprintf(file_url + url_len, "?token=%s&ts=%d", \
387 				token, (int)ts);
388 		}
389 
390 		printf("group_name=%s, remote_filename=%s\n", \
391 			group_name, remote_filename);
392 
393 		fdfs_get_file_info(group_name, remote_filename, &file_info);
394 
395 		printf("source ip address: %s\n", file_info.source_ip_addr);
396 		printf("file timestamp=%s\n", formatDatetime(
397 			file_info.create_timestamp, "%Y-%m-%d %H:%M:%S", \
398 			szDatetime, sizeof(szDatetime)));
399 		printf("file size=%"PRId64"\n", file_info.file_size);
400 		printf("file crc32=%u\n", file_info.crc32);
401 		printf("example file url: %s\n", file_url);
402 
403 		if (fdfs_gen_slave_filename(master_filename, \
404                		prefix_name, file_ext_name, \
405                 	slave_filename, &slave_filename_len) == 0)
406 		{
407 
408 			if (strcmp(remote_filename, slave_filename) != 0)
409 			{
410 				printf("slave_filename=%s\n" \
411 					"remote_filename=%s\n" \
412 					"not equal!\n", \
413 					slave_filename, remote_filename);
414 			}
415 		}
416 	}
417 	else if (strcmp(operation, "download") == 0 ||
418 		strcmp(operation, "getmeta") == 0 ||
419 		strcmp(operation, "setmeta") == 0 ||
420 		strcmp(operation, "query_servers") == 0 ||
421 		strcmp(operation, "delete") == 0)
422 	{
423 		if (argc < 5)
424 		{
425 			printf("Usage: %s <config_file> %s " \
426 				"<group_name> <remote_filename>\n", \
427 				argv[0], operation);
428 			fdfs_client_destroy();
429 			return EINVAL;
430 		}
431 
432 		snprintf(group_name, sizeof(group_name), "%s", argv[3]);
433 		snprintf(remote_filename, sizeof(remote_filename), \
434 				"%s", argv[4]);
435 		if (strcmp(operation, "setmeta") == 0 ||
436 	 	    strcmp(operation, "delete") == 0)
437 		{
438 			result = tracker_query_storage_update(pTrackerServer, \
439        	       			&storageServer, group_name, remote_filename);
440 		}
441 		else if (strcmp(operation, "query_servers") == 0)
442 		{
443 			ConnectionInfo storageServers[FDFS_MAX_SERVERS_EACH_GROUP];
444 			int server_count;
445 
446 			result = tracker_query_storage_list(pTrackerServer, \
447                 		storageServers, FDFS_MAX_SERVERS_EACH_GROUP, \
448                 		&server_count, group_name, remote_filename);
449 
450 			if (result != 0)
451 			{
452 				printf("tracker_query_storage_list fail, "\
453 					"group_name=%s, filename=%s, " \
454 					"error no: %d, error info: %s\n", \
455 					group_name, remote_filename, \
456 					result, STRERROR(result));
457 			}
458 			else
459 			{
460 				printf("server list (%d):\n", server_count);
461 				for (i=0; i<server_count; i++)
462 				{
463 					printf("\t%s:%d\n", \
464 						storageServers[i].ip_addr, \
465 						storageServers[i].port);
466 				}
467 				printf("\n");
468 			}
469 
470 			tracker_close_connection_ex(pTrackerServer, result != 0);
471 			fdfs_client_destroy();
472 			return result;
473 		}
474 		else
475 		{
476 			result = tracker_query_storage_fetch(pTrackerServer, \
477        	       			&storageServer, group_name, remote_filename);
478 		}
479 
480 		if (result != 0)
481 		{
482 			fdfs_client_destroy();
483 			printf("tracker_query_storage_fetch fail, " \
484 				"group_name=%s, filename=%s, " \
485 				"error no: %d, error info: %s\n", \
486 				group_name, remote_filename, \
487 				result, STRERROR(result));
488 			return result;
489 		}
490 
491 		printf("storage=%s:%d\n", storageServer.ip_addr, \
492 			storageServer.port);
493 
494 		if ((pStorageServer=tracker_make_connection(&storageServer, \
495 			&result)) == NULL)
496 		{
497 			fdfs_client_destroy();
498 			return result;
499 		}
500 
501 		if (strcmp(operation, "download") == 0)
502 		{
503 			if (argc >= 6)
504 			{
505 				local_filename = argv[5];
506 				if (strcmp(local_filename, "CALLBACK") == 0)
507 				{
508 				FILE *fp;
509 				fp = fopen(local_filename, "wb");
510 				if (fp == NULL)
511 				{
512 					result = errno != 0 ? errno : EPERM;
513 					printf("open file \"%s\" fail, " \
514 						"errno: %d, error info: %s", \
515 						local_filename, result, \
516 						STRERROR(result));
517 				}
518 				else
519 				{
520 				result = storage_download_file_ex( \
521 					pTrackerServer, pStorageServer, \
522 					group_name, remote_filename, 0, 0, \
523 					writeToFileCallback, fp, &file_size);
524 				fclose(fp);
525 				}
526 				}
527 				else
528 				{
529 				result = storage_download_file_to_file( \
530 					pTrackerServer, pStorageServer, \
531 					group_name, remote_filename, \
532 					local_filename, &file_size);
533 				}
534 			}
535 			else
536 			{
537 				file_buff = NULL;
538 				if ((result=storage_download_file_to_buff( \
539 					pTrackerServer, pStorageServer, \
540 					group_name, remote_filename, \
541 					&file_buff, &file_size)) == 0)
542 				{
543 					local_filename = strrchr( \
544 							remote_filename, '/');
545 					if (local_filename != NULL)
546 					{
547 						local_filename++;  //skip /
548 					}
549 					else
550 					{
551 						local_filename=remote_filename;
552 					}
553 
554 					result = writeToFile(local_filename, \
555 						file_buff, file_size);
556 
557 					free(file_buff);
558 				}
559 			}
560 
561 			if (result == 0)
562 			{
563 				printf("download file success, " \
564 					"file size=%"PRId64", file save to %s\n", \
565 					 file_size, local_filename);
566 			}
567 			else
568 			{
569 				printf("download file fail, " \
570 					"error no: %d, error info: %s\n", \
571 					result, STRERROR(result));
572 			}
573 		}
574 		else if (strcmp(operation, "getmeta") == 0)
575 		{
576 			if ((result=storage_get_metadata(pTrackerServer, \
577 				pStorageServer, group_name, remote_filename, \
578 				&pMetaList, &meta_count)) == 0)
579 			{
580 				printf("get meta data success, " \
581 					"meta count=%d\n", meta_count);
582 				for (i=0; i<meta_count; i++)
583 				{
584 					printf("%s=%s\n", \
585 						pMetaList[i].name, \
586 						pMetaList[i].value);
587 				}
588 
589 				free(pMetaList);
590 			}
591 			else
592 			{
593 				printf("getmeta fail, " \
594 					"error no: %d, error info: %s\n", \
595 					result, STRERROR(result));
596 			}
597 		}
598 		else if (strcmp(operation, "setmeta") == 0)
599 		{
600 			if (argc < 7)
601 			{
602 				printf("Usage: %s <config_file> %s " \
603 					"<group_name> <remote_filename> " \
604 					"<op_flag> <metadata_list>\n" \
605 					"\top_flag: %c for overwrite, " \
606 					"%c for merge\n" \
607 					"\tmetadata_list: name1=value1," \
608 					"name2=value2,...\n", \
609 					argv[0], operation, \
610 					STORAGE_SET_METADATA_FLAG_OVERWRITE, \
611 					STORAGE_SET_METADATA_FLAG_MERGE);
612 				fdfs_client_destroy();
613 				return EINVAL;
614 			}
615 
616 			meta_buff = strdup(argv[6]);
617 			if (meta_buff == NULL)
618 			{
619 				printf("Out of memory!\n");
620 				return ENOMEM;
621 			}
622 
623 			pMetaList = fdfs_split_metadata_ex(meta_buff, \
624 					',', '=', &meta_count, &result);
625 			if (pMetaList == NULL)
626 			{
627 				printf("Out of memory!\n");
628 				free(meta_buff);
629 				return ENOMEM;
630 			}
631 
632 			if ((result=storage_set_metadata(pTrackerServer, \
633 				NULL, group_name, remote_filename, \
634 				pMetaList, meta_count, *argv[5])) == 0)
635 			{
636 				printf("set meta data success\n");
637 			}
638 			else
639 			{
640 				printf("setmeta fail, " \
641 					"error no: %d, error info: %s\n", \
642 					result, STRERROR(result));
643 			}
644 
645 			free(meta_buff);
646 			free(pMetaList);
647 		}
648 		else if(strcmp(operation, "delete") == 0)
649 		{
650 			if ((result=storage_delete_file(pTrackerServer, \
651 			NULL, group_name, remote_filename)) == 0)
652 			{
653 				printf("delete file success\n");
654 			}
655 			else
656 			{
657 				printf("delete file fail, " \
658 					"error no: %d, error info: %s\n", \
659 					result, STRERROR(result));
660 			}
661 		}
662 	}
663 	else
664 	{
665 		fdfs_client_destroy();
666 		printf("invalid operation: %s\n", operation);
667 		return EINVAL;
668 	}
669 
670 	/* for test only */
671 	if ((result=fdfs_active_test(pTrackerServer)) != 0)
672 	{
673 		printf("active_test to tracker server %s:%d fail, errno: %d\n", \
674 			pTrackerServer->ip_addr, pTrackerServer->port, result);
675 	}
676 
677 	/* for test only */
678 	if ((result=fdfs_active_test(pStorageServer)) != 0)
679 	{
680 		printf("active_test to storage server %s:%d fail, errno: %d\n", \
681 			pStorageServer->ip_addr, pStorageServer->port, result);
682 	}
683 
684 	tracker_close_connection_ex(pStorageServer, true);
685 	tracker_close_connection_ex(pTrackerServer, true);
686 
687 	fdfs_client_destroy();
688 
689 	return result;
690 }
691 
692