# Get HDD and USB Stick Size and Manufacturer name



## overmind (May 20, 2011)

I need to get from C or from a script info for hard drives and usb sticks.

I get installed disks with:

```
sysctl kern.disks
```

Then for a hard drive is simple:

```
egrep ad6: /var/run/dmesg.boot | head -n1
```

I would get:

```
ad6: 152627MB <WDC WD1600JS-22NCB1 10.02E02> at ata3-master UDMA100 SATA 3Gb/s
```

Here I have all info I need.

The problem arise when I use usb sticks or hot swapable hard drives.
If I connect for example a 2G USB stick and then I remove it and I connect a 8G USB stick I will have two entries with *da0* name, and knowing that my devices is *da0* does not help because I don't know in /var/run/dmesg.boot which of them (the 2G one or the 8G one) is installed.

Also I am using *head -n 1* for hard drives but for usb sticks the sizeinfo is on third line:

```
da0: <Generic USB Flash Disk 0.00> Removable Direct Access SCSI-2 device 
da0: 1.000MB/s transfers
da0: 1927MB (3948543 512 byte sectors: 255H 63S/T 245C)
```

Also *da0* could be a SCSI drive in which case rules from hard drives applies (info on first line, not third).

So is there a way to know drive manufacturer/USB String-manufacturer by using only drive name that will apply to: IDE/SATA drives, SCSI/SAS drives and usb flashes?


----------



## expl (May 20, 2011)

statfs(2) if it is mounted.


----------



## overmind (May 20, 2011)

I would need drive size (not a particular partition size) and manufacturer name.


----------



## expl (May 20, 2011)

overmind said:
			
		

> I would need drive size (not a particular partition size) and manufacturer name.



You can calculate drive size via libgeom(3), I have no clue how to extract manufacturer information from a device using userland app other than parsing dmesg.


----------



## wblock@ (May 20, 2011)

file(1) will show device size:

```
# file -s /dev/ada0
/dev/ada0: x86 boot sector; partition 1: ID=0xa5, active, starthead 1, startsector 63, 1953520002 sectors, code offset 0x31
```

If you can figure out how to tell that /dev/da0 is a USB device, and which one, usbconfig(8) will show the manufacturer:

```
# usbconfig -d 1.2 dump_device_desc | grep iManufacturer
  iManufacturer = 0x0001  <Logitech>
```

camcontrol(8) might do that, too.


----------



## overmind (May 21, 2011)

Thank you that helps. After some test I'll be back and post how I did it.


----------



## expl (May 22, 2011)

I took a look at SCSI API documentation and it seem that vendor information can be extracted with INQUIRY command on all SCSI media (including USB disks). And the only way to issue it from userland on FreeBSD is by using the CAM interface. So here is a small piece of code that will display size and vendor info of a SCSI drive:


```
#include <sys/types.h>
#include <sys/disk.h>

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>

#include <camlib.h>

int main(int argc, char **argv){
	struct cam_device *cam_dev;
	off_t capacity;
	char name[30];
	
	int fd, unit;
	char *dev_path;
	
	if(argc != 2)
		return 1;
		
	memset(name, 0, sizeof(name));
		
	asprintf(&dev_path, "/dev/%s", argv[1]);
	assert(dev_path != NULL);
		
	assert((fd = open(dev_path, O_RDONLY)) > 0);	
	assert(ioctl(fd, DIOCGMEDIASIZE, &capacity) != -1);
	capacity = capacity / (1000 * 1000);
	
	close(fd);
	
	assert(cam_get_device(argv[1], name, sizeof(name), &unit) != -1);	
	assert(
	(cam_dev = cam_open_spec_device(name, unit, O_RDWR, NULL)) != NULL
	);
	
	printf("%s [%s]: size = %dMb(decimal)\n", 
	argv[1], cam_dev->inq_data.vendor, capacity);
	
	cam_close_device(cam_dev);
	
	return 0;
}
```

Sample output for my Nokia phone:

```
# ./udrive_info da0
da0 [Nokia   N8-00           1.0 ]: size = 15351Mb(decimal)
```


----------



## overmind (May 23, 2011)

@expl - Thank you, your solution is what I needed. I will use yours for SCSI/SAS, USB and I will take from dmesg for IDE/SATA.

It's possibly the same thing for IDE/SATA drives, of course with other system functions?


----------

