Is there a command that detects if the CD drawer is open or closed?

Solution 1:

I found a nice little solution here. The C code below, minimally changed from the linked site, will return an exit code of 0 if the tray is open and 1 if it is not.

So, save this code as something (e.g. foo.c) and compile it with this command:

gcc -o trayopen foo.c

Then, copy the compiled executable, trayopen to /usr/bin:

sudo cp trayopen /usr/bin

You should no be able to do things like

trayopen /dev/sr0 && echo closed

Or, more complete:

#!/bin/sh
if trayopen /dev/sr0
then
    echo "Tray is open."
else
    echo "Tray is closed."
fi

The code:

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/cdrom.h>

int main(int argc,char **argv) {
  int cdrom;
  int status=1;

  if (! argv[1] ){
    printf("Usage : trayopen [device]\n");
    printf("Result: Returns a 0 if the tray was open and 1 if it was closed\n");
    exit(2);
  }

  if ((cdrom = open(argv[1],O_RDONLY | O_NONBLOCK)) < 0) {
    printf("Unable to open device %s. Provide a device name (/dev/sr0, /dev/cdrom) as a parameter.\n",argv[1]);
    exit(2);
  }
  /* Check CD tray status */
  if (ioctl(cdrom,CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN) {
    status=0;
  }

  close(cdrom);
  exit(status);
}

Solution 2:

Based on @terdon's C code, I wrote a version in Python:

#!/usr/bin/python
import os, fcntl, CDROM, sys

def drive_status(drive):
  fd = os.open(drive, os.O_RDONLY | os.O_NONBLOCK)
  rv = fcntl.ioctl(fd, CDROM.CDROM_DRIVE_STATUS)
  os.close(fd)
  return rv

sys.exit(drive_status(sys.argv[1]) != CDROM.CDS_TRAY_OPEN)

Clearly, it could use some love for comments and cmdline argument handling, but if you need a Python version... this will work.

Also note that the CDROM module may be Linux-specific, and that not all drives support querying (eg. the ioctl() will return CDS_NO_INFO).

There are other CDROM.CDS_* constants that provide helpful variants. In particular, CDS_DISK_OK will tell you if the tray is closed and has a disk present.