fetus Diary

2008/01/27(日) - Linux で CD/DVD ドライブのトレイ開閉状態を取得するプログラム

#include <iostream>
#include <string>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>

#define DEFAULT_DEVICE "/dev/cdrom"

enum {
        RESULT_ERROR               = -1,
        RESULT_TRAY_CLOSED_DISC_OK = 0,
        RESULT_TRAY_CLOSED_DISC_NG = 1,
        RESULT_TRAY_OPENED         = 2,
};

bool IsBlockDevice(const std::string &device) {
        struct stat st;
        if(stat(device.c_str(), &st) == 0) {
                if(S_ISBLK(st.st_mode)) {
                        return true;
                } else {
                        std::cerr << device << " is not a block device" << std::endl;
                }
        } else {
                std::cerr << device << " stat() failed reason=" << errno << std::endl;
        }
        return false;
}

int main(int argc, char *argv[]) {
        std::string device;
        if(argc < 2) {
                if(!IsBlockDevice(DEFAULT_DEVICE)) {
                        std::cerr << "default device " << DEFAULT_DEVICE << " cannot use" << std::endl;
                        return RESULT_ERROR;
                }
                device = DEFAULT_DEVICE;
        } else if(IsBlockDevice(argv[1])) {
                device = argv[1];
        } else {
                return RESULT_ERROR;
        }

        int fd = open(device.c_str(), O_RDONLY | O_NONBLOCK);
        if(fd < 0) {
                std::cerr << "cannot open device: " << device << std::endl;
                return RESULT_ERROR;
        }
        const int result = ioctl(fd, CDROM_DRIVE_STATUS);

        close(fd);
        fd = -1;

        switch(result) {
        case CDS_DISC_OK:
                std::cout << "device " << device << " disc ok" << std::endl;
                return RESULT_TRAY_CLOSED_DISC_OK;

        case CDS_NO_DISC:
                std::cout << "device " << device << " no disc" << std::endl;
                return RESULT_TRAY_CLOSED_DISC_NG;

        case CDS_TRAY_OPEN:
                std::cout << "device " << device << " tray opened" << std::endl;
                return RESULT_TRAY_OPENED;

        case CDS_DRIVE_NOT_READY:
                std::cout << "device " << device << " not ready" << std::endl;
                break;

        default:
                std::cout << "device " << device << " status unknown (" << result << ")" << std::endl;
        }
        return RESULT_ERROR;
}

絶対誰か作ってると思うんだけどなぁ

# O_NONBLOCK しないと結構悲しい

Linux, C++, root 専用。"Linux 2.6.18-53.1.6.el5" "gcc version 4.1.2 20070626 (Red Hat 4.1.2-14)" x86_64 で動いているような気がする

動くかどうかは超環境依存。

関係あるかも?

このエントリは次のエントリから参照されているみたいです

コメント

コメントはありません。

名前
メール
コメント

※HTML タグは使えません。HTTP URL には自動リンクが張られます。

Captcha
画像から読み取れる文字を入力: