LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   CD/DVD autodetection (https://www.linuxquestions.org/questions/programming-9/cd-dvd-autodetection-334390/)

Chrax 06-16-2005 08:33 PM

CD/DVD autodetection
 
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.


All times are GMT -5. The time now is 01:36 PM.