Revision 9f23011a

b/block-raw-posix.c
55 55
#ifdef __FreeBSD__
56 56
#include <signal.h>
57 57
#include <sys/disk.h>
58
#include <sys/cdio.h>
58 59
#endif
59 60

  
60 61
#ifdef __OpenBSD__
......
110 111
    int fd_got_error;
111 112
    int fd_media_changed;
112 113
#endif
114
#if defined(__FreeBSD__)
115
    int cd_open_flags;
116
#endif
113 117
    uint8_t* aligned_buf;
114 118
} BDRVRawState;
115 119

  
......
117 121

  
118 122
static int fd_open(BlockDriverState *bs);
119 123

  
124
#if defined(__FreeBSD__)
125
static int cd_open(BlockDriverState *bs);
126
#endif
127

  
128
static int raw_is_inserted(BlockDriverState *bs);
129

  
120 130
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
121 131
{
122 132
    BDRVRawState *s = bs->opaque;
......
773 783
    int64_t size;
774 784
#ifdef HOST_BSD
775 785
    struct stat sb;
786
#ifdef __FreeBSD__
787
    int reopened = 0;
788
#endif
776 789
#endif
777 790
#ifdef __sun__
778 791
    struct dk_minfo minfo;
......
785 798
        return ret;
786 799

  
787 800
#ifdef HOST_BSD
801
#ifdef __FreeBSD__
802
again:
803
#endif
788 804
    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
789 805
#ifdef DIOCGMEDIASIZE
790 806
	if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
......
803 819
#else
804 820
        size = lseek(fd, 0LL, SEEK_END);
805 821
#endif
822
#ifdef __FreeBSD__
823
        switch(s->type) {
824
        case FTYPE_CD:
825
            /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */
826
            if (size == 2048LL * (unsigned)-1)
827
                size = 0;
828
            /* XXX no disc?  maybe we need to reopen... */
829
            if (size <= 0 && !reopened && cd_open(bs) >= 0) {
830
                reopened = 1;
831
                goto again;
832
            }
833
        }
834
#endif
806 835
    } else
807 836
#endif
808 837
#ifdef __sun__
......
993 1022
        bs->sg = 1;
994 1023
    }
995 1024
#endif
1025
#if defined(__FreeBSD__)
1026
    if (strstart(filename, "/dev/cd", NULL) ||
1027
        strstart(filename, "/dev/acd", NULL)) {
1028
        s->type = FTYPE_CD;
1029
        s->cd_open_flags = open_flags;
1030
    }
1031
#endif
1032
    s->fd = -1;
996 1033
    fd = open(filename, open_flags, 0644);
997 1034
    if (fd < 0) {
998 1035
        ret = -errno;
......
1001 1038
        return ret;
1002 1039
    }
1003 1040
    s->fd = fd;
1041
#if defined(__FreeBSD__)
1042
    /* make sure the door isnt locked at this time */
1043
    if (s->type == FTYPE_CD)
1044
        ioctl (s->fd, CDIOCALLOW);
1045
#endif
1004 1046
#if defined(__linux__)
1005 1047
    /* close fd so that we can reopen it as needed */
1006 1048
    if (s->type == FTYPE_FD) {
......
1167 1209

  
1168 1210
    return ioctl(s->fd, req, buf);
1169 1211
}
1170
#else
1212
#elif defined(__FreeBSD__)
1213

  
1214
static int fd_open(BlockDriverState *bs)
1215
{
1216
    BDRVRawState *s = bs->opaque;
1217

  
1218
    /* this is just to ensure s->fd is sane (its called by io ops) */
1219
    if (s->fd >= 0)
1220
        return 0;
1221
    return -EIO;
1222
}
1223

  
1224
static int cd_open(BlockDriverState *bs)
1225
{
1226
#if defined(__FreeBSD__)
1227
    BDRVRawState *s = bs->opaque;
1228
    int fd;
1229

  
1230
    switch(s->type) {
1231
    case FTYPE_CD:
1232
        /* XXX force reread of possibly changed/newly loaded disc,
1233
         * FreeBSD seems to not notice sometimes... */
1234
        if (s->fd >= 0)
1235
            close (s->fd);
1236
        fd = open(bs->filename, s->cd_open_flags, 0644);
1237
        if (fd < 0) {
1238
            s->fd = -1;
1239
            return -EIO;
1240
        }
1241
        s->fd = fd;
1242
        /* make sure the door isnt locked at this time */
1243
        ioctl (s->fd, CDIOCALLOW);
1244
    }
1245
#endif
1246
    return 0;
1247
}
1248

  
1249
static int raw_is_inserted(BlockDriverState *bs)
1250
{
1251
    BDRVRawState *s = bs->opaque;
1252

  
1253
    switch(s->type) {
1254
    case FTYPE_CD:
1255
        return (raw_getlength(bs) > 0);
1256
    case FTYPE_FD:
1257
        /* XXX handle this */
1258
        /* FALLTHRU */
1259
    default:
1260
        return 1;
1261
    }
1262
}
1263

  
1264
static int raw_media_changed(BlockDriverState *bs)
1265
{
1266
    return -ENOTSUP;
1267
}
1268

  
1269
static int raw_eject(BlockDriverState *bs, int eject_flag)
1270
{
1271
    BDRVRawState *s = bs->opaque;
1272

  
1273
    switch(s->type) {
1274
    case FTYPE_CD:
1275
        if (s->fd < 0)
1276
            return -ENOTSUP;
1277
        (void) ioctl (s->fd, CDIOCALLOW);
1278
        if (eject_flag) {
1279
            if (ioctl (s->fd, CDIOCEJECT) < 0)
1280
                perror("CDIOCEJECT");
1281
        } else {
1282
            if (ioctl (s->fd, CDIOCCLOSE) < 0)
1283
                perror("CDIOCCLOSE");
1284
        }
1285
        if (cd_open(bs) < 0)
1286
            return -ENOTSUP;
1287
        break;
1288
    case FTYPE_FD:
1289
        /* XXX handle this */
1290
        /* FALLTHRU */
1291
    default:
1292
        return -ENOTSUP;
1293
    }
1294
    return 0;
1295
}
1296

  
1297
static int raw_set_locked(BlockDriverState *bs, int locked)
1298
{
1299
    BDRVRawState *s = bs->opaque;
1300

  
1301
    switch(s->type) {
1302
    case FTYPE_CD:
1303
        if (s->fd < 0)
1304
            return -ENOTSUP;
1305
        if (ioctl (s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
1306
            /* Note: an error can happen if the distribution automatically
1307
               mounts the CD-ROM */
1308
            //        perror("CDROM_LOCKDOOR");
1309
        }
1310
        break;
1311
    default:
1312
        return -ENOTSUP;
1313
    }
1314
    return 0;
1315
}
1316

  
1317
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1318
{
1319
    return -ENOTSUP;
1320
}
1321
#else /* !linux && !FreeBSD */
1171 1322

  
1172 1323
static int fd_open(BlockDriverState *bs)
1173 1324
{
......
1198 1349
{
1199 1350
    return -ENOTSUP;
1200 1351
}
1201
#endif /* !linux */
1352
#endif /* !linux && !FreeBSD */
1202 1353

  
1203 1354
static int raw_sg_send_command(BlockDriverState *bs, void *buf, int count)
1204 1355
{

Also available in: Unified diff