I don't know if anybody saw my
earlier post, but please disregard it.
Those programs were early attempts at CD auto-detection, and while they worked, they had unreasonable dependencies for such simple programs.
I've written another program entirely in C that detects all optical drives and their capabilities, and what's more, it's only dependency is that you run Linux. (If there are any *nix folks out there that are not running Linux, I'd be very interested in ioctl information. I simply only have access to Linux at this point.)
Code:
#include <stdio.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <linux/cdrom.h>
char **optical_drives;
int *capabilities;
int num_drives;
/* find_devs - Recursively find all optical devices */
int find_devs(char *base){
DIR *base_dir;
struct dirent *file;
base_dir = opendir(base);
while((file = readdir(base_dir)) != NULL){
/* Ignore . and .. if readdir gives them to us */
if(strcmp((*file).d_name, ".") == 0 || strcmp((*file).d_name, "..") == 0)
continue;
/* An extra two characters to account for the \0 and potentially a slash */
char *file_name = malloc(strlen(base) + strlen((*file).d_name) + 2);
strcpy(file_name,base);
/* Make sure directory has a / after it before concatenating the file name */
if(file_name[strlen(base) - 1] != '/')
strcat(file_name,"/");
strcat(file_name,(*file).d_name);
/* For some reason, some symlinks act really oddly, so we're not going to
* bother with them. Besides, this will keep us from getting duplicates.
* I don't think devs can be hardlinked.
*/
struct stat stat_buffer;
if((lstat(file_name,&stat_buffer) == 0)){
if((stat_buffer.st_mode & S_IFMT) == S_IFLNK){
continue;
}
}
/* Check if it's a directory. If so, then search it. */
DIR *sub_dir;
if((sub_dir = opendir(file_name)) != NULL){
closedir(sub_dir);
find_devs(file_name);
}
/* If not, check for optical drives, and add them to the list */
else{
int fd = open(file_name,(O_RDONLY | O_EXCL | O_NONBLOCK),0);
if(fd >= 0){
/* Only optical drives return > 0 on the CDROM_GET_CAPABILITY ioctl
*
* nvidia devices return 0 for some reason. Fortunately, there seem
* to be no ill effects.
*/
int caps = ioctl(fd,CDROM_GET_CAPABILITY,NULL);
if(caps > 0){
if(num_drives == 0){
optical_drives = malloc(1);
capabilities = malloc(sizeof(int));
}
else{
realloc(optical_drives,num_drives + 1);
realloc(capabilities,sizeof(int) * (num_drives + 1));
}
if(optical_drives == NULL || capabilities == NULL){
printf("Allocation Error!\nDrives: %p\nCapabilities: %p\n",optical_drives,capabilities);
return 1;
}
strcpy(optical_drives[num_drives],file_name);
capabilities[num_drives] = caps;
num_drives++;
}
close(fd);
}
}
free(file_name);
}
closedir(base_dir);
return 0;
}
int main(int argc, char **argv){
num_drives = 0;
int errors = find_devs("/dev");
if(errors){
return 0;
}
for(;num_drives > 0; --num_drives){
char *device = optical_drives[num_drives - 1];
int caps = capabilities[num_drives - 1];
char *read, *write;
read = "CD";
write = "none";
if(caps & CDC_CD_R)
write = "CD-R";
if(caps & CDC_CD_RW)
write = "CD-RW";
if(caps & CDC_DVD)
read = "DVD";
if(caps & CDC_DVD_R){
if(strcmp(write,"CD-RW") == 0)
write = "DVD-RW";
else
write = "DVD-R";
}
if(caps & CDC_DVD_RAM)
write = "DVD-RAM";
printf("Device: %s\nRead: %s\nWrite: %s\n",device,read,write);
}
return 0;
}
The source is also downloadable at
http://personal.utulsa.edu/~chris-johnson/readdev.c
Compile it straight.
Code:
$ cc -oreaddev readdev.c
$ ./readdev
What I want to know is if this lists all of your optical drives and their capabilities. If you try this out, please take the time to respond.
(Note that I assume that a drive that can write CD-RW and DVD-R can write DVD-RW. This is because there is no flag for DVD-RW. I have never heard of a drive that could only write the former two, but not the latter, but if that is indeed the case, please tell me, and know that DVD-RW actually means that it can write CD-RW and DVD-R.)
Thanks,
Chris
Edit: Added a check that should allow devfs users to run this. Sorry if you tried it and had troubles.