Bug 135986 - [PATCH]: kioslave/media HAL backend support on FreeBSD
Summary: [PATCH]: kioslave/media HAL backend support on FreeBSD
Status: RESOLVED NOT A BUG
Alias: None
Product: kio
Classification: Unmaintained
Component: kioslave (other bugs)
Version First Reported In: unspecified
Platform: FreeBSD Ports FreeBSD
: NOR normal
Target Milestone: ---
Assignee: Konqueror Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-10-19 20:59 UTC by Maxim Samsonov
Modified: 2006-10-24 08:47 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Maxim Samsonov 2006-10-19 20:59:42 UTC
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:
Comment 1 Michael Nottebrock 2006-10-23 16:06:30 UTC
Please reassign to product media.
Comment 2 Maxim Samsonov 2006-10-23 20:17:02 UTC
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]
Comment 3 Tommi Tervo 2006-10-24 08:47:39 UTC
This one is now obsoleted by #136199