Version: (using KDE KDE 3.5.4) Installed from: FreeBSD Ports Compiler: gcc (GCC) 3.4.6 [FreeBSD] 20060305 OS: FreeBSD This patch enables HAL backend support for KDE media manager on FreeBSD. This patch suggests HALBackend::hasDirectory method which mimics, as close as possible, the LinuxCDPolling::hasDirectory method, adding FreeBSD specific issues. These issues are to go round the FreeBSD restriction on the cdrom device block size io limited to 2048 bytes. In addition it eliminates dependence on linuxcdpolling.h and linuxcdpolling.cpp which is not compiled during the library building. diff -rubdBN kioslave.orig/media/mediamanager/halbackend.cpp kioslave/media/mediamanager/halbackend.cpp --- kioslave.orig/media/mediamanager/halbackend.cpp Sat Jul 22 12:15:45 2006 +++ kioslave/media/mediamanager/halbackend.cpp Thu Oct 19 21:38:26 2006 @@ -17,7 +17,13 @@ */ #include "halbackend.h" + +#if defined(__FreeBSD__) +#include <fcntl.h> +#include <unistd.h> +#else #include "linuxcdpolling.h" +#endif #include <stdlib.h> @@ -397,6 +403,124 @@ delete m; } +#if defined(__FreeBSD__) + +bool HALBackend::hasDirectory(const QCString &devNode, const QCString &dir) +{ + bool ret = false; // return value + int fd = 0; // file descriptor for drive + unsigned short bs; // the discs block size + unsigned short bts; // the path table size (in blocks) + unsigned short ts; // the path table size (in bytes) + unsigned int btl; // the path table location (in blocks) + unsigned int tl; // the path table location (in bytes) + unsigned char len_di = 0; // length of the directory name in current path table entry + unsigned int parent = 0; // the number of the parent directory's path table entry + char dirname[256]; // filename for the current path table entry + int pos = 0; // our position into the path table + QCString fixed_directory = dir.upper(); // the uppercase version of the "directory" parameter + unsigned char buf[4096]; // the read buffer + unsigned char *sbuf = buf+2048; // the half part of the read buffer pointer + unsigned char *ptr; // the read buffer pointer + int rts; // the initial read path table size (in bytes) + + // open the drive + fd = open(devNode, O_RDONLY | O_NONBLOCK); + if (fd == -1) return false; + + // read the info block + lseek(fd, 0x8000, SEEK_SET); + if (read(fd, buf, 2048) != 2048) + { + close(fd); + return false; + } + // read the block size + bs = *(unsigned short *)(buf+0x80); + if (Q_BYTE_ORDER != Q_LITTLE_ENDIAN) + bs = ((bs << 8) & 0xFF00) | ((bs >> 8) & 0xFF); + + // read in size of path table + ts = *(unsigned short *)(buf+0x84); + if (Q_BYTE_ORDER != Q_LITTLE_ENDIAN) + ts = ((ts << 8) & 0xFF00) | ((ts >> 8) & 0xFF); + + // read in which block path table is in + btl = *(unsigned int *)(buf+0x8C); + if (Q_BYTE_ORDER != Q_LITTLE_ENDIAN) + btl = ((btl << 24) & 0xFF000000) | ((btl << 8) & 0xFF0000) | + ((btl >> 8) & 0xFF00) | ((btl >> 24) & 0xFF); + + // seek to the path table + tl = btl*bs; + lseek(fd, tl&(~0x7FF), SEEK_SET); + + // read the path table + bts = (ts+(tl&0x7FF))/2048; + rts = !bts ? 2048 : 4096; + if (read(fd, buf, rts) != rts) + { + close(fd); + return false; + } + if (bts) --bts; + ptr = buf+(tl&0x7FF); + + // loop through the path table entries + while (pos < ts) + { + // get the length of the filename of the current entry + len_di = *ptr; + + // get the record number of this entry's parent + // i'm pretty sure that the 1st entry is always the top directory + parent = *(unsigned short *)(ptr+6); + if (Q_BYTE_ORDER != Q_LITTLE_ENDIAN) + parent = ((parent << 8) & 0xFF00) | ((parent >> 8) & 0xFF); + + // read the name + bcopy(ptr+8, dirname, len_di); + dirname[len_di] = 0; + qstrcpy(dirname, QCString(dirname).upper()); + + // if we found a folder that has the root as a parent, and the directory name matches + // then return success + if ((parent == 1) && (dirname == fixed_directory)) + { + ret = true; + break; + } + + // all path table entries are padded to be even, so if this is an odd-length table, seek a byte to fix it + if (len_di%2 == 1) + { + ++pos; + ++ptr; + } + + // update our position + pos += 8 + len_di; + ptr += 8 + len_di; + if (bts && ptr >= sbuf ) + { + --bts; + ptr -= 2048; + bcopy(sbuf, buf, 2048); + // read the path table + if (read(fd, sbuf, 2048) != 2048) + { + close(fd); + return false; + } + } + } + + close(fd); + return ret; +} + +#endif + void HALBackend::setVolumeProperties(Medium* medium) { kdDebug(1219) << "HALBackend::setVolumeProperties for " << medium->id() << endl; @@ -461,15 +585,18 @@ else mimeType = "media/dvd" + MOUNT_SUFFIX; - if (libhal_volume_disc_has_audio(halVolume) && !libhal_volume_disc_has_data(halVolume)) - { - mimeType = "media/audiocd"; - medium->unmountableState( "audiocd:/?device=" + QString(libhal_volume_get_device_file(halVolume)) ); - } - - medium->setIconName(QString::null); - /* check if the disc id a vcd or a video dvd */ + if (libhal_volume_disc_has_data(halVolume)) + { +#if defined(__FreeBSD__) + QCString devNode = libhal_volume_get_device_file(halVolume); + if (hasDirectory(devNode, "video_ts")) + mimeType = "media/dvdvideo"; + else if (hasDirectory(devNode, "vcd")) + mimeType = "media/vcd"; + else if (hasDirectory(devNode, "svcd")) + mimeType = "media/svcd"; +#else DiscType type = LinuxCDPolling::identifyDiscType(libhal_volume_get_device_file(halVolume)); switch (type) { @@ -483,6 +610,15 @@ mimeType = "media/dvdvideo"; break; } +#endif + } + else if (libhal_volume_disc_has_audio(halVolume)) + { + mimeType = "media/audiocd"; + medium->unmountableState( "audiocd:/?device=" + QString(libhal_volume_get_device_file(halVolume)) ); + } + + medium->setIconName(QString::null); } else { diff -rubdBN kioslave.orig/media/mediamanager/halbackend.h kioslave/media/mediamanager/halbackend.h --- kioslave.orig/media/mediamanager/halbackend.h Sat Jul 22 12:15:45 2006 +++ kioslave/media/mediamanager/halbackend.h Thu Oct 19 21:41:19 2006 @@ -150,6 +150,9 @@ bool setFstabProperties(Medium* medium); void setCameraProperties(Medium* medium); QString generateName(const QString &devNode); +#if defined(__FreeBSD__) + bool hasDirectory(const QCString &devNode, const QCString &dir); +#endif static QString isInFstab(const Medium *medium); private slots:
Please reassign to product media.
I've reassigned this bug to product media. https://bugs.kde.org/show_bug.cgi?id=136199 On Monday 23 October 2006 18:06, Michael Nottebrock wrote: [bugs.kde.org quoted mail]
This one is now obsoleted by #136199