1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 */
17
18#define VERSION 1
19//#define PC
20
21#include <stdio.h>
22#include <string.h>
23#include <ctype.h>
24#include <stdlib.h>
25#include <unistd.h>
26#include <sys/vfs.h>
27#include <limits.h>
28#include <dirent.h>
29#include <bcmnvram.h>
30
31// From BusyBox and get volume's label.
32#include <autoconf.h>
33#include <volume_id_internal.h>
34#include <shared.h>
35
36#include "disk_initial.h"
37
38#define SYS_BLOCK "/sys/block"
39#define SYS_TTY "/sys/class/tty"
40#define SYS_USB "/sys/class/usb"
41#define SYS_SG "/sys/class/scsi_generic"
42
43#define USB_XHCI_PORT_1 get_usb_xhci_port(0)
44#define USB_XHCI_PORT_2 get_usb_xhci_port(1)
45#define USB_EHCI_PORT_1 get_usb_ehci_port(0)
46#define USB_EHCI_PORT_2 get_usb_ehci_port(1)
47#define USB_OHCI_PORT_1 get_usb_ohci_port(0)
48#define USB_OHCI_PORT_2 get_usb_ohci_port(1)
49#define USB_EHCI_PORT_3 get_usb_ehci_port(2)
50#define USB_OHCI_PORT_3 get_usb_ohci_port(2)
51
52#ifdef BCM_MMC
53#define SDCARD_PORT USB_EHCI_PORT_3
54#endif
55
56enum {
57	DEVICE_TYPE_UNKNOWN=0,
58	DEVICE_TYPE_DISK,
59	DEVICE_TYPE_PRINTER,
60	DEVICE_TYPE_SG,
61	DEVICE_TYPE_CD,
62	DEVICE_TYPE_MODEM,
63	DEVICE_TYPE_BECEEM
64};
65
66#define usb_dbg printf
67
68int isSerialNode(const char *device_name)
69{
70	if(strstr(device_name, "ttyUSB") == NULL)
71		return 0;
72
73	return 1;
74}
75
76int isACMNode(const char *device_name)
77{
78	if(strstr(device_name, "ttyACM") == NULL)
79		return 0;
80
81	return 1;
82}
83
84#ifdef RTCONFIG_USB_BECEEM
85int isBeceemNode(const char *device_name)
86{
87	if(strstr(device_name, "usbbcm") == NULL)
88		return 0;
89
90	return 1;
91}
92#endif
93
94int isStorageDevice(const char *device_name){
95	if(!strncmp(device_name, "sd", 2))
96		return 1;
97
98	return 0;
99}
100
101#ifdef BCM_MMC
102int isMMCDevice(const char *device_name){
103	if(!strncmp(device_name, "mmcblk", 6))
104		return 1;
105
106	return 0;
107}
108#endif
109
110int get_device_type_by_device(const char *device_name)
111{
112	if(device_name == NULL || strlen(device_name) <= 0){
113		usb_dbg("(%s): The device name is not correct.\n", device_name);
114		return DEVICE_TYPE_UNKNOWN;
115	}
116
117	if(isStorageDevice(device_name)
118#ifdef BCM_MMC
119			|| isMMCDevice(device_name) // SD card.
120#endif
121			){
122		return DEVICE_TYPE_DISK;
123	}
124#ifdef RTCONFIG_USB_PRINTER
125	if(!strncmp(device_name, "lp", 2)){
126		return DEVICE_TYPE_PRINTER;
127	}
128#endif
129#ifdef RTCONFIG_USB_MODEM
130	if(!strncmp(device_name, "sg", 2)){
131		return DEVICE_TYPE_SG;
132	}
133	if(!strncmp(device_name, "sr", 2)){
134		return DEVICE_TYPE_CD;
135	}
136	if(isSerialNode(device_name) || isACMNode(device_name)){
137		return DEVICE_TYPE_MODEM;
138	}
139#endif
140#ifdef RTCONFIG_USB_BECEEM
141	if(isBeceemNode(device_name)){
142		return DEVICE_TYPE_BECEEM;
143	}
144#endif
145
146	return DEVICE_TYPE_UNKNOWN;
147}
148
149#ifdef PC
150char *get_usb_port_by_device(const char *device_name, char *buf, const int buf_size){
151	int device_type = get_device_type_by_device(device_name);
152
153	if(device_type == DEVICE_TYPE_UNKNOWN)
154		return NULL;
155
156	memset(buf, 0, buf_size);
157	strcpy(buf, "1-1");
158
159	return buf;
160}
161#else
162char *get_usb_port_by_string(const char *target_string, char *buf, const int buf_size)
163{
164	memset(buf, 0, buf_size);
165
166	if(strstr(target_string, USB_XHCI_PORT_1))
167		strcpy(buf, USB_XHCI_PORT_1);
168	else if(strstr(target_string, USB_XHCI_PORT_2))
169		strcpy(buf, USB_XHCI_PORT_2);
170	else if(strstr(target_string, USB_EHCI_PORT_1))
171		strcpy(buf, USB_EHCI_PORT_1);
172	else if(strstr(target_string, USB_EHCI_PORT_2))
173		strcpy(buf, USB_EHCI_PORT_2);
174	else if(strstr(target_string, USB_OHCI_PORT_1))
175		strcpy(buf, USB_OHCI_PORT_1);
176	else if(strstr(target_string, USB_OHCI_PORT_2))
177		strcpy(buf, USB_OHCI_PORT_2);
178	else if(strstr(target_string, USB_EHCI_PORT_3))
179		strcpy(buf, USB_EHCI_PORT_3);
180	else if(strstr(target_string, USB_OHCI_PORT_3))
181		strcpy(buf, USB_OHCI_PORT_3);
182	else
183		return NULL;
184
185	return buf;
186}
187
188char *get_usb_port_by_device(const char *device_name, char *buf, const int buf_size)
189{
190	int device_type = get_device_type_by_device(device_name);
191	char device_path[128], usb_path[PATH_MAX];
192	char disk_name[16];
193
194	if(device_type == DEVICE_TYPE_UNKNOWN)
195		return NULL;
196
197	memset(device_path, 0, 128);
198	memset(usb_path, 0, PATH_MAX);
199
200	if(device_type == DEVICE_TYPE_DISK){
201		get_disk_name(device_name, disk_name, 16);
202		sprintf(device_path, "%s/%s/device", SYS_BLOCK, disk_name);
203		if(realpath(device_path, usb_path) == NULL){
204			usb_dbg("(%s): Fail to get link: %s.\n", device_name, device_path);
205			return NULL;
206		}
207	}
208	else
209#ifdef RTCONFIG_USB_PRINTER
210	if(device_type == DEVICE_TYPE_PRINTER){
211		sprintf(device_path, "%s/%s/device", SYS_USB, device_name);
212		if(realpath(device_path, usb_path) == NULL){
213			usb_dbg("(%s): Fail to get link: %s.\n", device_name, device_path);
214			return NULL;
215		}
216	}
217	else
218#endif
219#ifdef RTCONFIG_USB_MODEM
220	if(device_type == DEVICE_TYPE_SG){
221		sprintf(device_path, "%s/%s/device", SYS_SG, device_name);
222		if(realpath(device_path, usb_path) == NULL){
223			usb_dbg("(%s): Fail to get link: %s.\n", device_name, device_path);
224			return NULL;
225		}
226	}
227	else
228	if(device_type == DEVICE_TYPE_CD){
229		sprintf(device_path, "%s/%s/device", SYS_BLOCK, device_name);
230		if(realpath(device_path, usb_path) == NULL){
231			usb_dbg("(%s): Fail to get link: %s.\n", device_name, device_path);
232			return NULL;
233		}
234	}
235	else
236	if(device_type == DEVICE_TYPE_MODEM){
237		sprintf(device_path, "%s/%s/device", SYS_TTY, device_name);
238		if(realpath(device_path, usb_path) == NULL){
239			sleep(1); // Sometimes link would be built slowly, so try again.
240
241			if(realpath(device_path, usb_path) == NULL){
242				usb_dbg("(%s)(2/2): Fail to get link: %s.\n", device_name, device_path);
243				return NULL;
244			}
245		}
246	}
247	else
248#endif
249#ifdef RTCONFIG_USB_BECEEM
250	if(device_type == DEVICE_TYPE_BECEEM){
251		sprintf(device_path, "%s/%s/device", SYS_USB, device_name);
252		if(realpath(device_path, usb_path) == NULL){
253			if(realpath(device_path, usb_path) == NULL){
254				usb_dbg("(%s)(2/2): Fail to get link: %s.\n", device_name, device_path);
255				return NULL;
256			}
257		}
258	}
259	else
260#endif
261		return NULL;
262
263#ifdef BCM_MMC
264	if(isMMCDevice(device_name)){ // SD card.
265		snprintf(buf, buf_size, "%s", SDCARD_PORT);
266	}
267	else
268#endif
269	if(get_usb_port_by_string(usb_path, buf, buf_size) == NULL){
270		usb_dbg("(%s): Fail to get usb port: %s.\n", device_name, usb_path);
271		return NULL;
272	}
273
274	return buf;
275}
276#endif
277
278char *get_usb_node_by_string(const char *target_string, char *ret, const int ret_size)
279{
280	char usb_port[32], buf[16];
281	char *ptr, *ptr2, *ptr3;
282	int len;
283
284	memset(usb_port, 0, sizeof(usb_port));
285	if(get_usb_port_by_string(target_string, usb_port, sizeof(usb_port)) == NULL)
286		return NULL;
287	if((ptr = strstr(target_string, usb_port)) == NULL)
288		return NULL;
289	if(ptr != target_string)
290		ptr += strlen(usb_port)+1;
291
292	if((ptr2 = strchr(ptr, ':')) == NULL)
293		return NULL;
294	ptr3 = ptr2;
295	*ptr3 = 0;
296
297	if((ptr2 = strrchr(ptr, '/')) == NULL)
298		ptr2 = ptr;
299	else
300		ptr = ptr2+1;
301
302	len = strlen(ptr);
303	if(len > 16)
304		len = 16;
305
306	memset(buf, 0, sizeof(buf));
307	strncpy(buf, ptr, len);
308
309	len = strlen(buf);
310	if(len > ret_size)
311		len = ret_size;
312
313	memset(ret, 0, ret_size);
314	strncpy(ret, buf, len);
315
316	*ptr3 = ':';
317
318	return ret;
319}
320
321char *get_usb_node_by_device(const char *device_name, char *buf, const int buf_size)
322{
323	int device_type = get_device_type_by_device(device_name);
324	char device_path[128], usb_path[PATH_MAX];
325	char disk_name[16];
326
327	if(device_type == DEVICE_TYPE_UNKNOWN)
328		return NULL;
329
330	memset(device_path, 0, 128);
331	memset(usb_path, 0, PATH_MAX);
332
333	if(device_type == DEVICE_TYPE_DISK){
334		get_disk_name(device_name, disk_name, 16);
335		sprintf(device_path, "%s/%s/device", SYS_BLOCK, disk_name);
336		if(realpath(device_path, usb_path) == NULL){
337			usb_dbg("(%s): Fail to get link: %s.\n", device_name, device_path);
338			return NULL;
339		}
340	}
341	else
342#ifdef RTCONFIG_USB_PRINTER
343	if(device_type == DEVICE_TYPE_PRINTER){
344		sprintf(device_path, "%s/%s/device", SYS_USB, device_name);
345		if(realpath(device_path, usb_path) == NULL){
346			usb_dbg("(%s): Fail to get link: %s.\n", device_name, device_path);
347			return NULL;
348		}
349	}
350	else
351#endif
352#ifdef RTCONFIG_USB_MODEM
353	if(device_type == DEVICE_TYPE_SG){
354		sprintf(device_path, "%s/%s/device", SYS_SG, device_name);
355		if(realpath(device_path, usb_path) == NULL){
356			usb_dbg("(%s): Fail to get link: %s.\n", device_name, device_path);
357			return NULL;
358		}
359	}
360	else
361	if(device_type == DEVICE_TYPE_CD){
362		sprintf(device_path, "%s/%s/device", SYS_BLOCK, device_name);
363		if(realpath(device_path, usb_path) == NULL){
364			usb_dbg("(%s): Fail to get link: %s.\n", device_name, device_path);
365			return NULL;
366		}
367	}
368	else
369	if(device_type == DEVICE_TYPE_MODEM){
370		sprintf(device_path, "%s/%s/device", SYS_TTY, device_name);
371		if(realpath(device_path, usb_path) == NULL){
372			sleep(1); // Sometimes link would be built slowly, so try again.
373
374			if(realpath(device_path, usb_path) == NULL){
375				usb_dbg("(%s)(2/2): Fail to get link: %s.\n", device_name, device_path);
376				return NULL;
377			}
378		}
379	}
380	else
381#endif
382#ifdef RTCONFIG_USB_BECEEM
383	if(device_type == DEVICE_TYPE_BECEEM){
384		sprintf(device_path, "%s/%s/device", SYS_USB, device_name);
385		if(realpath(device_path, usb_path) == NULL){
386			if(realpath(device_path, usb_path) == NULL){
387				usb_dbg("(%s)(2/2): Fail to get link: %s.\n", device_name, device_path);
388				return NULL;
389			}
390		}
391	}
392	else
393#endif
394		return NULL;
395
396#ifdef BCM_MMC
397	if(isMMCDevice(device_name)){ // SD card.
398		snprintf(buf, buf_size, "%s", SDCARD_PORT);
399	}
400	else
401#endif
402	if(get_usb_node_by_string(usb_path, buf, buf_size) == NULL){
403		usb_dbg("(%s): Fail to get usb node: %s.\n", device_name, usb_path);
404		return NULL;
405	}
406
407	return buf;
408}
409
410char *get_path_by_node(const char *usb_node, char *buf, const int buf_size){
411	char usb_port[32], *hub_path;
412	int port_num = 0, len;
413
414	if(usb_node == NULL || buf == NULL || buf_size <= 0)
415		return NULL;
416
417	// Get USB port.
418	if(get_usb_port_by_string(usb_node, usb_port, sizeof(usb_port)) == NULL)
419		return NULL;
420
421	port_num = get_usb_port_number(usb_port);
422	if(port_num == 0)
423		return NULL;
424
425	if(strlen(usb_node) > (len = strlen(usb_port))){
426		hub_path = (char *)usb_node+len;
427		snprintf(buf, buf_size, "%d%s", port_num, hub_path);
428	}
429	else
430		snprintf(buf, buf_size, "%d", port_num);
431
432	return buf;
433}
434
435void strntrim(char *str){
436	register char *start, *end;
437	int len;
438
439	if(str == NULL)
440		return;
441
442	len = strlen(str);
443	start = str;
444	end = start+len-1;
445
446	while(start < end && isspace(*start))
447		++start;
448	while(start <= end && isspace(*end))
449		--end;
450
451	end++;
452
453	if((int)(end-start) < len){
454		memcpy(str, start, (end-start));
455		str[end-start] = 0;
456	}
457
458	return;
459}
460
461char *read_whole_file(const char *target) {
462	FILE *fp = fopen(target, "r");
463	char *buffer, *new_str;
464	int i;
465	unsigned int read_bytes = 0;
466	unsigned int each_size = 1024;
467
468	if (fp == NULL)
469		return NULL;
470
471	buffer = (char *)malloc(sizeof(char)*each_size+read_bytes);
472	if (buffer == NULL) {
473		usb_dbg("No memory \"buffer\".\n");
474		fclose(fp);
475		return NULL;
476	}
477	memset(buffer, 0, sizeof(char)*each_size+read_bytes);
478
479	while ((i = fread(buffer+read_bytes, each_size * sizeof(char), 1, fp)) == 1){
480		read_bytes += each_size;
481		new_str = (char *)malloc(sizeof(char)*each_size+read_bytes);
482		if (new_str == NULL) {
483			usb_dbg("No memory \"new_str\".\n");
484			free(buffer);
485			fclose(fp);
486			return NULL;
487		}
488		memset(new_str, 0, sizeof(char)*each_size+read_bytes);
489		memcpy(new_str, buffer, read_bytes);
490
491		free(buffer);
492		buffer = new_str;
493	}
494
495	fclose(fp);
496	return buffer;
497}
498
499char *get_line_from_buffer(const char *buf, char *line, const int line_size){
500	int buf_len, len;
501	char *ptr;
502
503	if(buf == NULL || (buf_len = strlen(buf)) <= 0)
504		return NULL;
505
506	if((ptr = strchr(buf, '\n')) == NULL)
507		ptr = (char *)(buf+buf_len);
508
509	if((len = ptr-buf) < 0)
510		len = buf-ptr;
511	++len; // include '\n'.
512
513	memset(line, 0, line_size);
514	strncpy(line, buf, len);
515
516	return line;
517}
518
519disk_info_t *read_disk_data(){
520	disk_info_t *disk_info_list = NULL, *new_disk_info, **follow_disk_info_list;
521	char *partition_info = read_whole_file(PARTITION_FILE);
522	char *follow_info;
523	char line[64], device_name[16];
524	u32 major;
525	disk_info_t *parent_disk_info;
526	partition_info_t *new_partition_info, **follow_partition_list;
527	u64 device_size;
528
529	if(partition_info == NULL){
530		usb_dbg("Failed to open \"%s\"!!\n", PARTITION_FILE);
531		return disk_info_list;
532	}
533	follow_info = partition_info;
534
535	memset(device_name, 0, 16);
536	while(get_line_from_buffer(follow_info, line, 64) != NULL){
537		follow_info += strlen(line);
538
539		if(sscanf(line, "%u %*u %llu %[^\n ]", &major, &device_size, device_name) != 3)
540			continue;
541		if(major != USB_DISK_MAJOR
542#ifdef BCM_MMC
543				&& major != MMC_DISK_MAJOR
544#endif
545				)
546			continue;
547		if(device_size == 1) // extend partition.
548			continue;
549
550		if(is_disk_name(device_name)){ // Disk
551			follow_disk_info_list = &disk_info_list;
552			while(*follow_disk_info_list != NULL)
553				follow_disk_info_list = &((*follow_disk_info_list)->next);
554
555			new_disk_info = create_disk(device_name, follow_disk_info_list);
556		}
557		else if(is_partition_name(device_name, NULL)){ // Partition
558			// Found a partition device.
559			// Find the parent disk.
560			parent_disk_info = disk_info_list;
561			while(1){
562				if(parent_disk_info == NULL){
563					usb_dbg("Error while parsing %s: found "
564									"partition '%s' but haven't seen the disk device "
565									"of which it is a part.\n", PARTITION_FILE, device_name);
566					free(partition_info);
567					return disk_info_list;
568				}
569
570				if(!strncmp(device_name, parent_disk_info->device, 3))
571					break;
572
573				parent_disk_info = parent_disk_info->next;
574			}
575
576			follow_partition_list = &(parent_disk_info->partitions);
577			while(*follow_partition_list != NULL){
578				if((*follow_partition_list)->partition_order == 0){
579					free_partition_data(follow_partition_list);
580					parent_disk_info->partitions = NULL;
581					follow_partition_list = &(parent_disk_info->partitions);
582				}
583				else
584					follow_partition_list = &((*follow_partition_list)->next);
585			}
586
587			new_partition_info = create_partition(device_name, follow_partition_list);
588			if(new_partition_info != NULL)
589				new_partition_info->disk = parent_disk_info;
590		}
591	}
592
593	free(partition_info);
594	return disk_info_list;
595}
596
597int is_disk_name(const char *device_name){
598	if(get_device_type_by_device(device_name) != DEVICE_TYPE_DISK)
599		return 0;
600
601#ifdef BCM_MMC
602	if(isMMCDevice(device_name)){
603		if(strchr(device_name, 'p'))
604			return 0;
605	}
606	else
607#endif
608	if(isdigit(device_name[strlen(device_name)-1]))
609		return 0;
610
611	return 1;
612}
613
614disk_info_t *create_disk(const char *device_name, disk_info_t **new_disk_info){
615	disk_info_t *follow_disk_info;
616	u32 major, minor;
617	u64 size_in_kilobytes = 0;
618	int len;
619	char usb_node[32], port_path[8];
620	char buf[64], *port, *vendor = NULL, *model = NULL, *ptr;
621	partition_info_t *new_partition_info, **follow_partition_list;
622
623	if(new_disk_info == NULL){
624		usb_dbg("Bad input!!\n");
625		return NULL;
626	}
627
628	*new_disk_info = NULL; // initial value.
629
630	if(device_name == NULL || !is_disk_name(device_name))
631		return NULL;
632
633	if(initial_disk_data(&follow_disk_info) == NULL){
634		usb_dbg("No memory!!(follow_disk_info)\n");
635		return NULL;
636	}
637
638	len = strlen(device_name);
639	follow_disk_info->device = (char *)malloc(len+1);
640	if(follow_disk_info->device == NULL){
641		usb_dbg("No memory!!(follow_disk_info->device)\n");
642		free_disk_data(&follow_disk_info);
643		return NULL;
644	}
645	strcpy(follow_disk_info->device, device_name);
646	follow_disk_info->device[len] = 0;
647
648	if(!get_disk_major_minor(device_name, &major, &minor)){
649		usb_dbg("Fail to get disk's major and minor: %s.\n", device_name);
650		free_disk_data(&follow_disk_info);
651		return NULL;
652	}
653	follow_disk_info->major = major;
654	follow_disk_info->minor = minor;
655
656	if(!get_disk_size(device_name, &size_in_kilobytes)){
657		usb_dbg("Fail to get disk's size_in_kilobytes: %s.\n", device_name);
658		free_disk_data(&follow_disk_info);
659		return NULL;
660	}
661	follow_disk_info->size_in_kilobytes = size_in_kilobytes;
662
663	if(isStorageDevice(device_name)
664#ifdef BCM_MMC
665			|| isMMCDevice(device_name)
666#endif
667			){
668		// Get USB node.
669		if(get_usb_node_by_device(device_name, usb_node, 32) == NULL){
670			usb_dbg("(%s): Fail to get usb node.\n", device_name);
671			free_disk_data(&follow_disk_info);
672			return NULL;
673		}
674
675		if(get_path_by_node(usb_node, port_path, 8) == NULL){
676			usb_dbg("(%s): Fail to get usb path.\n", usb_node);
677			free_disk_data(&follow_disk_info);
678			return NULL;
679		}
680
681		// Get USB port.
682		if(get_usb_port_by_string(usb_node, buf, 64) == NULL){
683			usb_dbg("Fail to get usb port: %s.\n", usb_node);
684			free_disk_data(&follow_disk_info);
685			return NULL;
686		}
687
688		len = strlen(buf);
689		if(len > 0){
690			port = (char *)malloc(8);
691			if(port == NULL){
692				usb_dbg("No memory!!(port)\n");
693				free_disk_data(&follow_disk_info);
694				return NULL;
695			}
696			memset(port, 0, 8);
697			strncpy(port, port_path, 8);
698
699			follow_disk_info->port = port;
700		}
701
702		// start get vendor.
703		get_disk_vendor(device_name, buf, 64);
704
705		len = strlen(buf);
706		if(len > 0){
707			vendor = (char *)malloc(len+1);
708			if(vendor == NULL){
709				usb_dbg("No memory!!(vendor)\n");
710				free_disk_data(&follow_disk_info);
711				return NULL;
712			}
713			strncpy(vendor, buf, len);
714			vendor[len] = 0;
715			strntrim(vendor);
716
717			follow_disk_info->vendor = vendor;
718		}
719
720		// start get model.
721		get_disk_model(device_name, buf, 64);
722
723		len = strlen(buf);
724		if(len > 0){
725			model = (char *)malloc(len+1);
726			if(model == NULL){
727				usb_dbg("No memory!!(model)\n");
728				free_disk_data(&follow_disk_info);
729				return NULL;
730			}
731			strncpy(model, buf, len);
732			model[len] = 0;
733			strntrim(model);
734
735			follow_disk_info->model = model;
736		}
737
738		// get USB's tag
739		memset(buf, 0, 64);
740		len = 0;
741		ptr = buf;
742		if(vendor != NULL){
743			len += strlen(vendor);
744			strcpy(ptr, vendor);
745			ptr += len;
746		}
747		if(model != NULL){
748			if(len > 0){
749				++len; // Add a space between vendor and model.
750				strcpy(ptr, " ");
751				++ptr;
752			}
753			len += strlen(model);
754			strcpy(ptr, model);
755			ptr += len;
756		}
757
758		if(len > 0){
759			follow_disk_info->tag = (char *)malloc(len+1);
760			if(follow_disk_info->tag == NULL){
761				usb_dbg("No memory!!(follow_disk_info->tag)\n");
762				free_disk_data(&follow_disk_info);
763				return NULL;
764			}
765			strcpy(follow_disk_info->tag, buf);
766			follow_disk_info->tag[len] = 0;
767		}
768		else{
769#ifdef BCM_MMC
770			if(isMMCDevice(device_name))
771				len = strlen(DEFAULT_MMC_TAG);
772			else
773#endif
774				len = strlen(DEFAULT_USB_TAG);
775
776			follow_disk_info->tag = (char *)malloc(len+1);
777			if(follow_disk_info->tag == NULL){
778				usb_dbg("No memory!!(follow_disk_info->tag)\n");
779				free_disk_data(&follow_disk_info);
780				return NULL;
781			}
782#ifdef BCM_MMC
783			if(isMMCDevice(device_name))
784				strcpy(follow_disk_info->tag, DEFAULT_MMC_TAG);
785			else
786#endif
787				strcpy(follow_disk_info->tag, DEFAULT_USB_TAG);
788			follow_disk_info->tag[len] = 0;
789		}
790
791		follow_partition_list = &(follow_disk_info->partitions);
792		while(*follow_partition_list != NULL)
793			follow_partition_list = &((*follow_partition_list)->next);
794
795		new_partition_info = create_partition(device_name, follow_partition_list);
796		if(new_partition_info != NULL){
797			new_partition_info->disk = follow_disk_info;
798
799			++(follow_disk_info->partition_number);
800			++(follow_disk_info->mounted_number);
801			if(!strcmp(new_partition_info->device, follow_disk_info->device))
802				new_partition_info->size_in_kilobytes = follow_disk_info->size_in_kilobytes-4;
803		}
804	}
805
806	if(!strcmp(follow_disk_info->device, follow_disk_info->partitions->device))
807		get_disk_partitionnumber(device_name, &(follow_disk_info->partition_number), &(follow_disk_info->mounted_number));
808
809	*new_disk_info = follow_disk_info;
810
811	return *new_disk_info;
812}
813
814disk_info_t *initial_disk_data(disk_info_t **disk_info_list){
815	disk_info_t *follow_disk;
816
817	if(disk_info_list == NULL)
818		return NULL;
819
820	*disk_info_list = (disk_info_t *)malloc(sizeof(disk_info_t));
821	if(*disk_info_list == NULL)
822		return NULL;
823
824	follow_disk = *disk_info_list;
825
826	follow_disk->tag = NULL;
827	follow_disk->vendor = NULL;
828	follow_disk->model = NULL;
829	follow_disk->device = NULL;
830	follow_disk->major = (u32)0;
831	follow_disk->minor = (u32)0;
832	follow_disk->port = NULL;
833	follow_disk->partition_number = (u32)0;
834	follow_disk->mounted_number = (u32)0;
835	follow_disk->size_in_kilobytes = (u64)0;
836	follow_disk->partitions = NULL;
837	follow_disk->next = NULL;
838
839	return follow_disk;
840}
841
842void free_disk_data(disk_info_t **disk_info_list){
843	disk_info_t *follow_disk, *old_disk;
844
845	if(disk_info_list == NULL)
846		return;
847
848	follow_disk = *disk_info_list;
849	while(follow_disk != NULL){
850		if(follow_disk->tag != NULL)
851			free(follow_disk->tag);
852		if(follow_disk->vendor != NULL)
853			free(follow_disk->vendor);
854		if(follow_disk->model != NULL)
855			free(follow_disk->model);
856		if(follow_disk->device != NULL)
857			free(follow_disk->device);
858		if(follow_disk->port != NULL)
859			free(follow_disk->port);
860
861		free_partition_data(&(follow_disk->partitions));
862
863		old_disk = follow_disk;
864		follow_disk = follow_disk->next;
865		free(old_disk);
866	}
867}
868
869int get_disk_major_minor(const char *disk_name, u32 *major, u32 *minor){
870	FILE *fp;
871	char target_file[128], buf[8], *ptr;
872
873	if(major == NULL || minor == NULL)
874		return 0;
875
876	*major = 0; // initial value.
877	*minor = 0; // initial value.
878
879	if(disk_name == NULL || !is_disk_name(disk_name))
880		return 0;
881
882	memset(target_file, 0, 128);
883	sprintf(target_file, "%s/%s/dev", SYS_BLOCK, disk_name);
884	if((fp = fopen(target_file, "r")) == NULL)
885		return 0;
886
887	memset(buf, 0, 8);
888	ptr = fgets(buf, 8, fp);
889	fclose(fp);
890	if(ptr == NULL)
891		return 0;
892
893	if((ptr = strchr(buf, ':')) == NULL)
894		return 0;
895
896	ptr[0] = '\0';
897	*major = (u32)strtol(buf, NULL, 10);
898	*minor = (u32)strtol(ptr+1, NULL, 10);
899
900	return 1;
901}
902
903int get_disk_size(const char *disk_name, u64 *size_in_kilobytes){
904	FILE *fp;
905	char target_file[128], buf[16], *ptr;
906
907	if(size_in_kilobytes == NULL)
908		return 0;
909
910	*size_in_kilobytes = 0; // initial value.
911
912	if(disk_name == NULL || !is_disk_name(disk_name))
913		return 0;
914
915	memset(target_file, 0, 128);
916	sprintf(target_file, "%s/%s/size", SYS_BLOCK, disk_name);
917	if((fp = fopen(target_file, "r")) == NULL)
918		return 0;
919
920	memset(buf, 0, 16);
921	ptr = fgets(buf, 16, fp);
922	fclose(fp);
923	if(ptr == NULL)
924		return 0;
925
926	*size_in_kilobytes = ((u64)strtoll(buf, NULL, 10))/2;
927
928	return 1;
929}
930
931char *get_disk_vendor(const char *disk_name, char *buf, const int buf_size){
932	FILE *fp;
933	char target_file[128], *ptr;
934	int len;
935
936	if(buf_size <= 0)
937		return NULL;
938	memset(buf, 0, buf_size);
939
940	if(disk_name == NULL || !is_disk_name(disk_name))
941		return NULL;
942
943	memset(target_file, 0, 128);
944	sprintf(target_file, "%s/%s/device/vendor", SYS_BLOCK, disk_name);
945	if((fp = fopen(target_file, "r")) == NULL)
946		return NULL;
947
948	ptr = fgets(buf, buf_size, fp);
949	fclose(fp);
950	if(ptr == NULL)
951		return NULL;
952
953	len = strlen(buf);
954	buf[len-1] = 0;
955
956	return buf;
957}
958
959char *get_disk_model(const char *disk_name, char *buf, const int buf_size){
960	FILE *fp;
961	char target_file[128], *ptr;
962	int len;
963
964	if(buf_size <= 0)
965		return NULL;
966	memset(buf, 0, buf_size);
967
968	if(disk_name == NULL || !is_disk_name(disk_name))
969		return NULL;
970
971	memset(target_file, 0, 128);
972	sprintf(target_file, "%s/%s/device/model", SYS_BLOCK, disk_name);
973	if((fp = fopen(target_file, "r")) == NULL)
974		return NULL;
975
976	ptr = fgets(buf, buf_size, fp);
977	fclose(fp);
978	if(ptr == NULL)
979		return NULL;
980
981	len = strlen(buf);
982	buf[len-1] = 0;
983
984	return buf;
985}
986
987int get_disk_partitionnumber(const char *string, u32 *partition_number, u32 *mounted_number){
988	char disk_name[16];
989	char target_path[128];
990	DIR *dp;
991	struct dirent *file;
992	int len;
993	char *mount_info = NULL, target[8];
994
995	if(string == NULL)
996		return 0;
997
998	if(partition_number == NULL)
999		return 0;
1000
1001	*partition_number = 0; // initial value.
1002	if(mounted_number != NULL){
1003		*mounted_number = 0; // initial value.
1004		mount_info = read_whole_file(MOUNT_FILE);
1005	}
1006
1007	len = strlen(string);
1008	if(!is_disk_name(string)){
1009		while(isdigit(string[len-1]))
1010			--len;
1011
1012#ifdef BCM_MMC
1013		if(string[len-1] == 'p')
1014			--len;
1015#endif
1016	}
1017	else if(mounted_number != NULL && mount_info != NULL){
1018		memset(target, 0, 8);
1019		sprintf(target, "%s ", string);
1020		if(strstr(mount_info, target) != NULL)
1021			++(*mounted_number);
1022	}
1023	memset(disk_name, 0, 16);
1024	strncpy(disk_name, string, len);
1025
1026	memset(target_path, 0, 128);
1027	sprintf(target_path, "%s/%s", SYS_BLOCK, disk_name);
1028	if((dp = opendir(target_path)) == NULL){
1029		if(mount_info != NULL)
1030			free(mount_info);
1031		return 0;
1032	}
1033
1034	len = strlen(disk_name);
1035	while((file = readdir(dp)) != NULL){
1036		if(file->d_name[0] == '.')
1037			continue;
1038
1039		if(!strncmp(file->d_name, disk_name, len)){
1040			++(*partition_number);
1041
1042			if(mounted_number == NULL || mount_info == NULL)
1043				continue;
1044
1045			memset(target, 0, 8);
1046			sprintf(target, "%s ", file->d_name);
1047			if(strstr(mount_info, target) != NULL)
1048				++(*mounted_number);
1049		}
1050	}
1051	closedir(dp);
1052	if(mount_info != NULL)
1053		free(mount_info);
1054
1055	return 1;
1056}
1057
1058int is_partition_name(const char *device_name, u32 *partition_order){
1059	int order;
1060	u32 partition_number;
1061
1062	if(partition_order != NULL)
1063		*partition_order = 0;
1064
1065	if(get_device_type_by_device(device_name) != DEVICE_TYPE_DISK)
1066		return 0;
1067
1068	// get the partition number in the device_name
1069#ifdef BCM_MMC
1070	if(isMMCDevice(device_name)) // SD card: mmcblk0p1.
1071		order = (u32)strtol(device_name+8, NULL, 10);
1072	else // sda1.
1073#endif
1074		order = (u32)strtol(device_name+3, NULL, 10);
1075	if(order <= 0 || order == LONG_MIN || order == LONG_MAX)
1076		return 0;
1077
1078	if(!get_disk_partitionnumber(device_name, &partition_number, NULL))
1079		return 0;
1080
1081	if(partition_order != NULL)
1082		*partition_order = order;
1083
1084	return 1;
1085}
1086
1087int find_partition_label(const char *dev_name, char *label){
1088	struct volume_id id;
1089	char dev_path[128];
1090	char usb_port[32];
1091	char nvram_label[32], nvram_value[512];
1092
1093	if(label) *label = 0;
1094
1095	memset(usb_port, 0, 32);
1096	if(get_usb_port_by_device(dev_name, usb_port, 32) == NULL)
1097		return 0;
1098
1099	memset(nvram_label, 0, 32);
1100	sprintf(nvram_label, "usb_path_%s_label", dev_name);
1101
1102	memset(nvram_value, 0, 512);
1103	strncpy(nvram_value, nvram_safe_get(nvram_label), 512);
1104	if(strlen(nvram_value) > 0){
1105		strcpy(label, nvram_value);
1106
1107		return (label && *label != 0);
1108	}
1109
1110	memset(dev_path, 0, 128);
1111	sprintf(dev_path, "/dev/%s", dev_name);
1112
1113	memset(&id, 0x00, sizeof(id));
1114	if((id.fd = open(dev_path, O_RDONLY)) < 0)
1115		return 0;
1116
1117	volume_id_get_buffer(&id, 0, SB_BUFFER_SIZE);
1118
1119	if(volume_id_probe_linux_swap(&id) == 0 || id.error)
1120		goto ret;
1121	if(volume_id_probe_ext(&id) == 0 || id.error)
1122		goto ret;
1123	if(volume_id_probe_vfat(&id) == 0 || id.error)
1124		goto ret;
1125	if(volume_id_probe_ntfs(&id) == 0 || id.error)
1126		goto ret;
1127	if(volume_id_probe_hfs_hfsplus(&id) == 0 || id.error)
1128		goto ret;
1129
1130ret:
1131	volume_id_free_buffer(&id);
1132	if(label && (*id.label != 0))
1133		strcpy(label, id.label);
1134	else
1135		strcpy(label, " ");
1136	nvram_set(nvram_label, label);
1137	close(id.fd);
1138	return (label && *label != 0);
1139}
1140
1141partition_info_t *create_partition(const char *device_name, partition_info_t **new_part_info){
1142	partition_info_t *follow_part_info;
1143	char label[128];
1144	u32 partition_order = 0;
1145	u64 size_in_kilobytes = 0, total_kilobytes = 0, used_kilobytes = 0;
1146	char buf1[PATH_MAX], buf2[64], buf3[PATH_MAX]; // options of mount info needs more buffer size.
1147	int len;
1148
1149	if(new_part_info == NULL){
1150		usb_dbg("Bad input!!\n");
1151		return NULL;
1152	}
1153
1154	*new_part_info = NULL; // initial value.
1155
1156	if(device_name == NULL || get_device_type_by_device(device_name) != DEVICE_TYPE_DISK)
1157		return NULL;
1158
1159	if(!is_disk_name(device_name) && !is_partition_name(device_name, &partition_order))
1160		return NULL;
1161
1162	if(initial_part_data(&follow_part_info) == NULL){
1163		usb_dbg("No memory!!(follow_part_info)\n");
1164		return NULL;
1165	}
1166
1167	len = strlen(device_name);
1168	follow_part_info->device = (char *)malloc(len+1);
1169	if(follow_part_info->device == NULL){
1170		usb_dbg("No memory!!(follow_part_info->device)\n");
1171		free_partition_data(&follow_part_info);
1172		return NULL;
1173	}
1174	strncpy(follow_part_info->device, device_name, len);
1175	follow_part_info->device[len] = 0;
1176
1177	if(find_partition_label(device_name, label)){
1178		strntrim(label);
1179		len = strlen(label);
1180		follow_part_info->label = (char *)malloc(len+1);
1181		if(follow_part_info->label == NULL){
1182			usb_dbg("No memory!!(follow_part_info->label)\n");
1183			free_partition_data(&follow_part_info);
1184			return NULL;
1185		}
1186		strncpy(follow_part_info->label, label, len);
1187		follow_part_info->label[len] = 0;
1188	}
1189
1190	follow_part_info->partition_order = partition_order;
1191
1192	if(read_mount_data(device_name, buf1, PATH_MAX, buf2, 64, buf3, PATH_MAX)){
1193		len = strlen(buf1);
1194		follow_part_info->mount_point = (char *)malloc(len+1);
1195		if(follow_part_info->mount_point == NULL){
1196			usb_dbg("No memory!!(follow_part_info->mount_point)\n");
1197			free_partition_data(&follow_part_info);
1198			return NULL;
1199		}
1200		strncpy(follow_part_info->mount_point, buf1, len);
1201		follow_part_info->mount_point[len] = 0;
1202
1203		len = strlen(buf2);
1204		follow_part_info->file_system = (char *)malloc(len+1);
1205		if(follow_part_info->file_system == NULL){
1206			usb_dbg("No memory!!(follow_part_info->file_system)\n");
1207			free_partition_data(&follow_part_info);
1208			return NULL;
1209		}
1210		strncpy(follow_part_info->file_system, buf2, len);
1211		follow_part_info->file_system[len] = 0;
1212
1213		len = strlen(buf3);
1214		follow_part_info->permission = (char *)malloc(len+1);
1215		if(follow_part_info->permission == NULL){
1216			usb_dbg("No memory!!(follow_part_info->permission)\n");
1217			free_partition_data(&follow_part_info);
1218			return NULL;
1219		}
1220		strncpy(follow_part_info->permission, buf3, len);
1221		follow_part_info->permission[len] = 0;
1222
1223		if(get_mount_size(follow_part_info->mount_point, &total_kilobytes, &used_kilobytes)){
1224			follow_part_info->size_in_kilobytes = total_kilobytes;
1225			follow_part_info->used_kilobytes = used_kilobytes;
1226		}
1227	}
1228	else{
1229		/*if(is_disk_name(device_name)){	// Disk
1230			free_partition_data(&follow_part_info);
1231			return NULL;
1232		}
1233		else{//*/
1234			len = strlen(PARTITION_TYPE_UNKNOWN);
1235			follow_part_info->file_system = (char *)malloc(len+1);
1236			if(follow_part_info->file_system == NULL){
1237				usb_dbg("No memory!!(follow_part_info->file_system)\n");
1238				free_partition_data(&follow_part_info);
1239				return NULL;
1240			}
1241			strncpy(follow_part_info->file_system, PARTITION_TYPE_UNKNOWN, len);
1242			follow_part_info->file_system[len] = 0;
1243
1244			get_partition_size(device_name, &size_in_kilobytes);
1245			follow_part_info->size_in_kilobytes = size_in_kilobytes;
1246		//}
1247	}
1248
1249	*new_part_info = follow_part_info;
1250
1251	return *new_part_info;
1252}
1253
1254partition_info_t *initial_part_data(partition_info_t **part_info_list){
1255	partition_info_t *follow_part;
1256
1257	if(part_info_list == NULL)
1258		return NULL;
1259
1260	*part_info_list = (partition_info_t *)malloc(sizeof(partition_info_t));
1261	if(*part_info_list == NULL)
1262		return NULL;
1263
1264	follow_part = *part_info_list;
1265
1266	follow_part->device = NULL;
1267	follow_part->label = NULL;
1268	follow_part->partition_order = (u32)0;
1269	follow_part->mount_point = NULL;
1270	follow_part->file_system = NULL;
1271	follow_part->permission = NULL;
1272	follow_part->size_in_kilobytes = (u64)0;
1273	follow_part->used_kilobytes = (u64)0;
1274	follow_part->disk = NULL;
1275	follow_part->next = NULL;
1276
1277	return follow_part;
1278}
1279
1280void free_partition_data(partition_info_t **partition_info_list){
1281	partition_info_t *follow_partition, *old_partition;
1282
1283	if(partition_info_list == NULL)
1284		return;
1285
1286	follow_partition = *partition_info_list;
1287	while(follow_partition != NULL){
1288		if(follow_partition->device != NULL)
1289			free(follow_partition->device);
1290		if(follow_partition->label != NULL)
1291			free(follow_partition->label);
1292		if(follow_partition->mount_point != NULL)
1293			free(follow_partition->mount_point);
1294		if(follow_partition->file_system != NULL)
1295			free(follow_partition->file_system);
1296		if(follow_partition->permission != NULL)
1297			free(follow_partition->permission);
1298
1299		follow_partition->disk = NULL;
1300
1301		old_partition = follow_partition;
1302		follow_partition = follow_partition->next;
1303		free(old_partition);
1304	}
1305}
1306
1307int get_partition_size(const char *partition_name, u64 *size_in_kilobytes){
1308	FILE *fp;
1309	char disk_name[16];
1310	char target_file[128], buf[16], *ptr;
1311
1312	if(size_in_kilobytes == NULL)
1313		return 0;
1314
1315	*size_in_kilobytes = 0; // initial value.
1316
1317	if(!is_partition_name(partition_name, NULL))
1318		return 0;
1319
1320	get_disk_name(partition_name, disk_name, 16);
1321
1322	memset(target_file, 0, 128);
1323	sprintf(target_file, "%s/%s/%s/size", SYS_BLOCK, disk_name, partition_name);
1324	if((fp = fopen(target_file, "r")) == NULL)
1325		return 0;
1326
1327	memset(buf, 0, 16);
1328	ptr = fgets(buf, 16, fp);
1329	fclose(fp);
1330	if(ptr == NULL)
1331		return 0;
1332
1333	*size_in_kilobytes = ((u64)strtoll(buf, NULL, 10))/2;
1334
1335	return 1;
1336}
1337
1338int read_mount_data(const char *device_name
1339		, char *mount_point, int mount_len
1340		, char *type, int type_len
1341		, char *right, int right_len
1342		){
1343	char *mount_info = read_whole_file(MOUNT_FILE);
1344	char *start, line[PATH_MAX];
1345	char target[8];
1346
1347	if(mount_point == NULL || mount_len <= 0
1348			|| type == NULL || type_len <= 0
1349			|| right == NULL || right_len <= 0
1350			){
1351		usb_dbg("Bad input!!\n");
1352		return 0;
1353	}
1354
1355	if(mount_info == NULL){
1356		usb_dbg("Failed to open \"%s\"!!\n", MOUNT_FILE);
1357		return 0;
1358	}
1359
1360	memset(target, 0, 8);
1361	sprintf(target, "%s ", device_name);
1362
1363	if((start = strstr(mount_info, target)) == NULL){
1364		//usb_dbg("disk_initial:: %s: Failed to execute strstr()!\n", device_name);
1365		free(mount_info);
1366		return 0;
1367	}
1368
1369	start += strlen(target);
1370
1371	if(get_line_from_buffer(start, line, PATH_MAX) == NULL){
1372		usb_dbg("%s: Failed to execute get_line_from_buffer()!\n", device_name);
1373		free(mount_info);
1374		return 0;
1375	}
1376
1377	memset(mount_point, 0, mount_len);
1378	memset(type, 0, type_len);
1379	memset(right, 0, right_len);
1380
1381	if(sscanf(line, "%s %s %[^\n ]", mount_point, type, right) != 3){
1382		usb_dbg("%s: Failed to execute sscanf()!\n", device_name);
1383		free(mount_info);
1384		return 0;
1385	}
1386
1387	if(!strcmp(type, "ufsd")){
1388		char full_dev[16];
1389
1390		memset(full_dev, 0, 16);
1391		sprintf(full_dev, "/dev/%s", device_name);
1392
1393		memset(type, 0, type_len);
1394		strcpy(type, detect_fs_type(full_dev));
1395	}
1396
1397	right[2] = 0;
1398
1399	free(mount_info);
1400	return 1;
1401}
1402
1403int get_mount_path(const char *const pool, char *mount_path, int mount_len){
1404	char type[64], right[PATH_MAX];
1405
1406	return read_mount_data(pool, mount_path, mount_len, type, 64, right, PATH_MAX);
1407}
1408
1409int get_mount_size(const char *mount_point, u64 *total_kilobytes, u64 *used_kilobytes){
1410	u64 total_size, free_size, used_size;
1411	struct statfs fsbuf;
1412
1413	if(total_kilobytes == NULL || used_kilobytes == NULL)
1414		return 0;
1415
1416	*total_kilobytes = 0;
1417	*used_kilobytes = 0;
1418
1419	if(statfs(mount_point, &fsbuf))
1420		return 0;
1421
1422	total_size = (u64)((u64)fsbuf.f_blocks*(u64)fsbuf.f_bsize);
1423	free_size = (u64)((u64)fsbuf.f_bfree*(u64)fsbuf.f_bsize);
1424	used_size = total_size-free_size;
1425
1426	*total_kilobytes = total_size/1024;
1427	*used_kilobytes = used_size/1024;
1428
1429	return 1;
1430}
1431
1432char *get_disk_name(const char *string, char *buf, const int buf_size){
1433	int len;
1434
1435	if(string == NULL || buf_size <= 0)
1436		return NULL;
1437	memset(buf, 0, buf_size);
1438
1439	if(!is_disk_name(string) && !is_partition_name(string, NULL))
1440		return NULL;
1441
1442	len = strlen(string);
1443	if(!is_disk_name(string)){
1444		while(isdigit(string[len-1]))
1445			--len;
1446
1447#ifdef BCM_MMC
1448		if(string[len-1] == 'p')
1449			--len;
1450#endif
1451	}
1452
1453	if(len > buf_size)
1454		return NULL;
1455
1456	strncpy(buf, string, len);
1457
1458	return buf;
1459}
1460
1461void print_disk(const disk_info_t *const disk_info){
1462	if(disk_info == NULL){
1463		usb_dbg("No disk!\n");
1464		return;
1465	}
1466
1467	usb_dbg("Disk:\n");
1468	usb_dbg("              tag: %s.\n", disk_info->tag);
1469	usb_dbg("           vendor: %s.\n", disk_info->vendor);
1470	usb_dbg("            model: %s.\n", disk_info->model);
1471	usb_dbg("           device: %s.\n", disk_info->device);
1472	usb_dbg("            major: %u.\n", disk_info->major);
1473	usb_dbg("            minor: %u.\n", disk_info->minor);
1474	usb_dbg("             port: %s.\n", disk_info->port);
1475	usb_dbg(" partition_number: %u.\n", disk_info->partition_number);
1476	usb_dbg("   mounted_number: %u.\n", disk_info->mounted_number);
1477	usb_dbg("size_in_kilobytes: %llu.\n", disk_info->size_in_kilobytes);
1478
1479	print_partitions(disk_info->partitions);
1480}
1481
1482void print_disks(const disk_info_t *const disk_list){
1483	disk_info_t *follow_disk;
1484
1485	if(disk_list == NULL){
1486		usb_dbg("No disk list!\n");
1487		return;
1488	}
1489
1490	for(follow_disk = (disk_info_t *)disk_list; follow_disk != NULL; follow_disk = follow_disk->next)
1491		print_disk(follow_disk);
1492}
1493
1494void print_partition(const partition_info_t *const partition_info){
1495	if(partition_info == NULL){
1496		usb_dbg("No partition!\n");
1497		return;
1498	}
1499
1500	usb_dbg("Partition:\n");
1501	if(partition_info->disk != NULL)
1502		usb_dbg("      Parent disk: %s.\n", partition_info->disk->device);
1503	usb_dbg("           device: %s.\n", partition_info->device);
1504	usb_dbg("            label: %s.\n", partition_info->label);
1505	usb_dbg("  partition_order: %u.\n", partition_info->partition_order);
1506	usb_dbg("      mount_point: %s.\n", partition_info->mount_point);
1507	usb_dbg("      file_system: %s.\n", partition_info->file_system);
1508	usb_dbg("       permission: %s.\n", partition_info->permission);
1509	usb_dbg("size_in_kilobytes: %llu.\n", partition_info->size_in_kilobytes);
1510	usb_dbg("   used_kilobytes: %llu.\n", partition_info->used_kilobytes);
1511}
1512
1513void print_partitions(const partition_info_t *const partition_list){
1514	partition_info_t *follow_partition;
1515
1516	if(partition_list == NULL){
1517		usb_dbg("No partition list!\n");
1518		return;
1519	}
1520
1521	for(follow_partition = (partition_info_t *)partition_list; follow_partition != NULL; follow_partition = follow_partition->next)
1522		print_partition(follow_partition);
1523}
1524
1525int main(int argc, char *argv[]){
1526	disk_info_t *disk_info, *disk_list;
1527	partition_info_t *partition_info;
1528	char buf[PATH_MAX];
1529
1530	usb_dbg("%d: Using myself to get information:\n", VERSION);
1531
1532	if(argc == 3){
1533		get_mount_path("sdb1", buf, PATH_MAX);
1534		printf("buf=%s.\n", buf);
1535	}
1536	else if(argc == 2){
1537		if(is_disk_name(argv[1])){ // Disk
1538			usb_dbg("%d: Get disk(%s)'s information:\n", VERSION, argv[1]);
1539
1540			create_disk(argv[1], &disk_info);
1541
1542			print_disk(disk_info);
1543
1544			free_disk_data(&disk_info);
1545		}
1546		else{
1547			usb_dbg("%d: Get partition(%s)'s information:\n", VERSION, argv[1]);
1548
1549			create_partition(argv[1], &partition_info);
1550
1551			print_partition(partition_info);
1552
1553			free_partition_data(&partition_info);
1554		}
1555	}
1556	else{
1557		usb_dbg("%d: Get all Disk information:\n", VERSION);
1558
1559		disk_list = read_disk_data();
1560
1561		print_disks(disk_list);
1562
1563		free_disk_data(&disk_list);
1564	}
1565
1566	return 0;
1567}
1568