ISO 9660 is a international standard that defines a filesystem for CD/DVD media. To get the volume name from such system in Linux we'll be dealing with the its device path once again. On my system the device path of the CD/DVD device is
/dev/scd0.
Also, it is important to know where is this information stored on the CD. Surfing and google-ing around I found
the site that explains ISO 9660 in detail: types, modes, sectors etc.
Field of interest (called
Volume ID) is located in the sector 16 called
Primary Volume Descriptor on the 32808. byte of the CD, and its length is 32 bytes.
Those include directives are important for the compilation:
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <string.h>
- #include <unistd.h>
Next, function that can read chunk of data from the filesystem at specific byte is needed:
- int fs_read_data ( char * fs, int seek, int len, char * data)
- {
- unsigned int fd;
- int result = -1;
- if ( fs != NULL)
- {
- if ( ( fd = open (fs, O_RDONLY)) != -1)
- {
- if ( lseek (fd, seek, SEEK_SET) != -1)
- {
- if ( read ( fd, data, len) != -1)
- {
- data[len] = '\0';
- result = 0;
- }
- }
- }
- close ( fd);
- }
- return result;
- }
Function
fs_read_data takes four arguments. String
fs is a device path of a iso9660 filesystem, variable
seek is a byte number at which we start reading data,
len is number of bytes to read and
data is a character buffer that stores the read data.
If the
fs string is NULL, function returns -1 as a result, otherwise the device file is opened and data is being read from it.
Function
open (
read more) tries to open the device file representing our filesystem (
/dev/scd0). Upon successful completion, the function shall open the file and return a non-negative integer representing the lowest numbered unused file descriptor; otherwise, -1 shall be returned. Second argument of the
open function says to open the file for rading only.
Function
lseek (
read more) at line 9 sets the number of bytes to skip for the current file descriptor. In this case the number 32808 will be passed.
Finally, data is being read with the function
read (
read more) at line 11. It reads the
len number of bytes from the file associated with the
fd file descriptor and puts that chunk of bytes into
data buffer. In our case the
len will be 32.
If all the conditions of the
if statements are true the function
fs_read_data will return 0 and
data will be filled. Character '\0' marks the end of the string.
The
main function is now constructed like this:
- int main() {
- char * fs = "/dev/scd0";
- int seek =32808;
- int len = 32;
- char * buff = NULL;
- char * volume_name = NULL;
- buff = malloc( (sizeof (buff)) * (len+1));
-
- if ( fs_read_data ( fs, seek, len, buff) != -1)
- {
- if ( (strncmp ( buff, "NO NAME", 7) == 0) || ( strncmp (buff, " ",1) == 0))
- {
- free ( buff);
- buff=NULL;
- volume_name = "None";
- }
- else
- {
- volume_name = strdup ( buff);
- }
- }
- printf("%s", volume_name);
- free (buff);
- buff=NULL;
- return 0;
- }
All important variables are declared in first 7 lines. Notice that
malloc function is used to allocate 32 bytes in the buffer
buff.
The
if statement at line 9 tries to read wanted
Volume ID field from the /dev/scd0 device file representing my CD/DVD device. Next,
strcmp function is used to check if the string on that field is empty string ("") or it says "NO NAME". If either of that is true the volume name of the ISO 9660 filesystem isn't set, the
buff is freed and "None" is assigned to the
volume_name char array. Otherwise, the content of the
buff is duplicated into
volume_name. At the end volume name is printed on the screen.