Get HD/Partition serial number - c++

When Using Windows I can get a (more or less unique) serial number of a HDD partition by using command
GetVolumeInformation()
My question: is there something similar available for Linux? Means a number that would change only when somebody formats a partition and that can be retrieved programmatically?
Thanks!

In linux, you could use the blkid command to get the UUID of the partition:
# blkid /dev/sda1
/dev/sda1: UUID="15677362-cef3-4a53-aca3-3bace1b0d92a" TYPE="ext4"
This info is stored in the formatting of specific partition types like ext4, xfs and changes when reformatted. There is no info available for unformatted partitions.
If you need to call it from code, calling out to a shell to run this command isn't exactly the prettiest way to do it, but it could work:
#include <stdio.h>
int main(int argc,char ** argv) {
/* device you are looking for */
char device[]="/dev/sda1";
/* buffer to hold info */
char buffer[1024];
/* format into a single command to be run */
sprintf(buffer,"/sbin/blkid -o value %s",device);
/* run the command via popen */
FILE *f=popen(buffer,"r");
/* probably should check to make sure f!=null */
/* read the first line of output */
fgets(buffer,sizeof(buffer),f);
/* print the results (note, newline is included in string) */
fprintf(stdout,"uuid is %s",buffer);
}

You can use udev to get the serial number of the device. (You'll need to know the device name though)
struct udev *context = udev_new();
struct udev_device *device = udev_device_new_from_syspath(context, "/sys/block/sda");
const char *id = udev_device_get_property_value(device, "ID_SERIAL");
// Cleanup
udev_device_unref(device);
udev_unref(context);

Partitions have (at least) three identities in linux:
The raw device identifier (think cat /proc/partitions) - this is not a unique serial number
The UUID of the partition - can be found with blkid, and stored within the partition itself. You can also manually parse /dev/.blkid.tab - the format being obvious.
The disk label - also stored within the partition. EG:
lsblk -o name,mountpoint,label,uuid
NAME MOUNTPOINT LABEL UUID
sda
├─sda1 / 315eaf50-adcc-4f0d-b767-f008f3f1c194
├─sda2
└─sda5 [SWAP] 1ff31705-f488-44a4-ba5f-e2fe9eff4b96
sr0
Of these, the second is closest to what you want. To read it programatically, use libblkid.

Related

How a program in C++ can interface with shell scripts in Linux by using 'system' variables?

I have a shell script running on Linux that essentially takes a photo with a Webcam at intervals of 30s and stores the result in a directory, replacing the old image by overwriting it.
This photo is then read by a program written in C++, but once it is executed asynchronously to the script, I would like to use a semaphore in that script so that when I was about to update a new photo (say 5 sec before), the script indicates in this flag the unavailability of the picture for access to any other program.
The first thing that came to my mind was the script simply writing this information in a text file and the C++ program reads it back to know the status, but that struck me as a rough solution.
Another thing I thought, it was the C++ program itself to instantiate the script at 30s intervals, by using the command exec("./<script>.sh") but since this program is not always running, wont work.
So, I wonder how to use some kind of "dynamic" system variable (if it exists), something that acts as a RAM, so that I can use it as a flag where the script indicates some status, and the program then reads it.
It is possible ?
Based on the above tips, I got the solution based on 'named pipes' approach. What lies behind this is that FIFOs are essentially treated by the operacional system as 'files', so they can be manipulated with the same standard system libraries that are already available. Just sharing the CPP code used for testing:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/stat.h>
#define FIFO_FILE "MYFIFO"
int main(void)
{
FILE *fp;
char readbuf[80];
int StrCnt = 0 ;
/* Create the FIFO if it does not exist */
umask(0);
mknod(FIFO_FILE, S_IFIFO|0666, 0);
while(1)
{
fp = fopen(FIFO_FILE, "r");
if ( fp > 0 )
{
fgets(readbuf, 80, fp);
printf("Received %d\th string : %s\n", StrCnt++ , readbuf);
fclose(fp);
// remove(FIFO_FILE);
rewind(fp);
}
}
return(0);
}
I can put values to MYFIFO with e the following command:
echo "abcde12345" > MYFIFO
And ls -al command shows FIFO content, 10 characters + 1 null character, if code not running:
-rw-rw-r-- 1 esp8266 esp8266 11 10 22 16:10 MYFIFO
Whereas if the code is running, it empties the buffer (above function rewind()):
prw-rw-rw- 1 esp8266 esp8266 0 10 22 16:12 MYFIFO

C++ Check if mount path is still mounted

I have the details of the mount path (specifically mount prefix) as obtained using getmntent
in the structure as defined below:
struct mntent {
char *mnt_fsname; /* name of mounted file system */
char *mnt_dir; /* file system path prefix */
char *mnt_type; /* mount type (see mntent.h) */
char *mnt_opts; /* mount options (see mntent.h) */
int mnt_freq; /* dump frequency in days */
int mnt_passno; /* pass number on parallel fsck */
};
Using mnt_dir I want to check if the mount path is still mounted after a while as it is possible that before some processing is done on it, it might have been unmounted.
What is the most efficient way to check if the path is still mounted?
Also Is there a way to get callback in case the path gets unmounted?
I'd say that the most efficient way is to cache st_dev and st_ino returned by stat() (although probably caching just st_dev should be enough).
If the volume gets unmounted, the mount point reverts to the empty subdirectory in the parent filesystem where the volume was originally mounted, and stat() will return a different device+inode, for the same file path.
As far as being notified, poke around the inotify(7) interface, paying attention to the IN_UNMOUNT event.

How to get USB Drive Label in Linux?

I am trying to get USB drive's Label in my c/c++ Application. I am using libudev to get the usb details. But it doesn't provides the drives Label. Does any one have an idea on how to get the drive Label. I am working on embedded platform, it doesn't have a /dev/disk folder.
Please Help.
Kernel Version : 3.3.8
Normally, a usb filesystem has a vfat partition on it to make it compatible between msdos, windows, linux and mac architectures.
The label is a property of the vfat filesystem. It appears normaly as the first directory entry in the root directory and marked as a filesystem label. Recent implementations of msdos filesystems (merely vfat exfat and fat32) write it also in a fixed part of the boot record for that partition, so you can read it from there.
You have volume serial-number at offset 0x43 (4 bytes) in the first sector of the partition.
You have also a copy of the volume label at offset 0x47 in that first sector also (11 bytes length)
The trick is: as normally a usb stick is partitioned (with only one partition) you have to:
look in the first sector of the usb stick for the partition table and locate the first parition.
then, look in the first sector of that parition, locate byte offset 0x43 and use that four bytes as volume serial number (it matches UUID="..." in /etc/fstab linux file) and the eleven bytes that follow for the volume label.
Note
Be careful that NTFS doesn't use that place for that purpose and you can damage a NTFS partition writing there. Just read from that place.
Note 2
Also, don't try to write to that place even in vfat filesystems, as they also maintain a copy of the volume label in the root directory of the filesystem.
Note 3
The easiest way to get the label of a dos filesystem (and ext[234], ntfs, etc) in linux is with the command blkid(8) it gives the followind output:
/dev/sda1: UUID="0b2741c0-90f5-48d7-93ce-6a03d2e8e9aa" TYPE="ext4"
/dev/sda5: UUID="62e2cbf2-d847-4048-856a-a90b91116285" TYPE="crypto_LUKS"
/dev/mapper/sda5_crypt: UUID="vnBDh3-bcaR-Cu7E-ok5D-oeFp-5SyP-MmAEsb" TYPE="LVM2_member"
/dev/mapper/my_vg-root: UUID="1b9f158b-35b5-490e-b914-bdc70e7f5c28" TYPE="ext4"
/dev/mapper/my_vg-swap_1: UUID="36b8ac81-7043-42ae-9f2a-908d53e2a2b3" TYPE="swap"
/dev/sdb1: LABEL="K003_1G" UUID="641B-80BF" TYPE="vfat"
As you can see, the last entry is for a vfat usb pendrive, but you have to parse this output (I think is not difficult to do)
I believe the "label" of a disk is a property maintained by the file system it's using, i.e. it's not at the USB level.
You're going to need the proper file system implementation, i.e. "mount" the disk.
You can use blkid to read the USB device label:
blkid USB_PATH | grep -o ""LABEL.*"" | cut -d'\"' -f2

How to create a program to list all the USB devices in a Mac?

I have a limited exposure to the Mac OS X operating system and now I have started using Xcode and am studying about I/O kit. I need to create a program in Xcode under command line tool in order to list all USB devices connected in a Mac system. Those who have previous experience under this, please help me. If anyone could provide me with sample code then it will be of great use, as I am looking for starting point.
You can adapt USBPrivateDataSample to your needs, the sample sets up a notifier, lists the currently attached devices, then waits for device attach/detach. If you do, you will want to remove the usbVendor and usbProduct matching dictionaries, so all USB devices are matched.
Alternately, you can use IOServiceGetMatchingServices to get an iterator for all current matching services, using a dictionary created by IOServiceMatching(kIOUSBDeviceClassName).
Here's a short sample (which I've never run):
#include <IOKit/IOKitLib.h>
#include <IOKit/usb/IOUSBLib.h>
int main(int argc, const char *argv[])
{
CFMutableDictionaryRef matchingDict;
io_iterator_t iter;
kern_return_t kr;
io_service_t device;
/* set up a matching dictionary for the class */
matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
if (matchingDict == NULL)
{
return -1; // fail
}
/* Now we have a dictionary, get an iterator.*/
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr != KERN_SUCCESS)
{
return -1;
}
/* iterate */
while ((device = IOIteratorNext(iter)))
{
/* do something with device, eg. check properties */
/* ... */
/* And free the reference taken before continuing to the next item */
IOObjectRelease(device);
}
/* Done, release the iterator */
IOObjectRelease(iter);
return 0;
}
You just need to access the IOKit Registry. You may well be able to use the ioreg tool to do this (e.g. run it via system() or popen()). If not then you can at least use it to verify your code:
Info on ioreg tool:
$ man ioreg
Get list of USB devices:
$ ioreg -Src IOUSBDevice
If you run system_profiler SPUSBDataType it'll list all the USB devices connected to the system, you can then interact with that data either by dumping it into a text file or reading it from the command into the application and working with it there.

Is a file opened in another application?

Is there a way for me to tell if a particular file is open in another application?
I have a feature I'd like to provide before opening a file in my application, i want to know whether the file is already opened or not.
I want to put the functionality that if its already opened in another application then my application restrict the file to open it again to save the loss of information.
thanks in advance...
There is file locking for this kind of tasks:
http://linux.die.net/man/2/flock
On Linux, you can use "lsof" to see if the file is open.
http://linux.about.com/library/cmd/blcmdl8_lsof.htm
You must have implemented some solution by now but, the way i understand your design, I suggest against your it.
You should allow the user to open the file and check the for time stamps to find out if its been modified before allowing user to save the file (may be ask user whether to overwrite the file or save it as new file etc.).
Look at stat() API.
-Before you open the file note down the timestamp (st_mtime, see structure below)
-Let users modify the file.
-Before user saves the file check the timestamp of the file again st_mtime and if it differs then ask questions to the user.
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};