From 6ced92452c2712c91e850d1012332cfb6704f3da Mon Sep 17 00:00:00 2001 From: Julian Harnath Date: Sat, 11 Feb 2017 22:34:11 +0000 Subject: [PATCH] FUSE compat: add MIME type faking * Add special handling for reading the BEOS:TYPE attribute to supply on-the-fly fake MIME types for FUSE module filesystems, the same way it's done in our FAT and NTFS FS modules * Reuse the mime_ext_table which we already have and put it into a shared location so we don't get further extra copies of it --- headers/private/file_systems/mime_ext_table.h | 24 +++ .../file_systems/shared/mime_ext_table.c | 156 ++++++++++++++++++ .../userlandfs/server/fuse/FUSEVolume.cpp | 48 +++++- .../userlandfs/server/fuse/Jamfile | 5 +- 4 files changed, 224 insertions(+), 9 deletions(-) create mode 100644 headers/private/file_systems/mime_ext_table.h create mode 100644 src/add-ons/kernel/file_systems/shared/mime_ext_table.c diff --git a/headers/private/file_systems/mime_ext_table.h b/headers/private/file_systems/mime_ext_table.h new file mode 100644 index 0000000000..4b9b316ecd --- /dev/null +++ b/headers/private/file_systems/mime_ext_table.h @@ -0,0 +1,24 @@ +/* + Copyright 1999-2001, Be Incorporated. All Rights Reserved. + This file may be used under the terms of the Be Sample Code License. +*/ + +#ifndef MIME_TYPES_H +#define MIME_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + + +extern const char* kAttrMimeTypeName; + +extern status_t set_mime(const char** mime, const char* filename); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/src/add-ons/kernel/file_systems/shared/mime_ext_table.c b/src/add-ons/kernel/file_systems/shared/mime_ext_table.c new file mode 100644 index 0000000000..6c6e926b0e --- /dev/null +++ b/src/add-ons/kernel/file_systems/shared/mime_ext_table.c @@ -0,0 +1,156 @@ +/* + Copyright 1999-2001, Be Incorporated. All Rights Reserved. + This file may be used under the terms of the Be Sample Code License. +*/ + +#include + +#include + +#include + + +struct ext_mime { + char *extension; + char *mime; +}; + +static struct ext_mime mimes[] = { + { "gz", "application/x-gzip" }, + { "hqx", "application/x-binhex40" }, + { "lha", "application/x-lharc" }, + { "pcl", "application/x-pcl" }, + { "pdf", "application/pdf" }, + { "ps", "application/postscript" }, + { "sit", "application/x-stuff-it" }, + { "tar", "application/x-tar" }, + { "tgz", "application/x-gzip" }, + { "uue", "application/x-uuencode" }, + { "z", "application/x-compress" }, + { "zip", "application/zip" }, + { "zoo", "application/x-zoo" }, + { "rar", "application/x-rar" }, + { "pkg", "application/x-scode-UPkg" }, + { "7z", "application/x-7z-compressed" }, + { "bz2", "application/x-bzip2" }, + { "xz", "application/x-xz" }, + + { "jar", "application/x-jar" }, + + { "aif", "audio/x-aiff" }, + { "aiff", "audio/x-aiff" }, + { "au", "audio/basic" }, + { "mid", "audio/x-midi" }, + { "midi", "audio/x-midi" }, + { "mod", "audio/mod" }, + { "ra", "audio/x-real-audio" }, + { "wav", "audio/x-wav" }, + { "mp3", "audio/x-mpeg" }, + { "ogg", "audio/x-vorbis" }, + { "flac", "audio/x-flac" }, + { "wma", "audio/x-ms-wma" }, + + { "avi", "video/x-msvideo" }, + { "mov", "video/quicktime" }, + { "qt", "video/quicktime" }, + { "mpg", "video/mpeg" }, + { "mpeg", "video/mpeg" }, + { "flv", "video/x-flv" }, + { "mp4", "video/mp4" }, + { "mkv", "video/x-matroska" }, + { "asf", "application/x-asf" }, + { "rm", "video/vnd.rn-realvideo" }, + { "wmv", "video/x-ms-wmv" }, + + { "bmp", "image/x-bmp" }, + { "fax", "image/g3fax" }, + { "gif", "image/gif" }, + { "iff", "image/x-iff" }, + { "jpg", "image/jpeg" }, + { "jpeg", "image/jpeg" }, + { "pbm", "image/x-portable-bitmap" }, + { "pcx", "image/x-pcx" }, + { "pgm", "image/x-portable-graymap" }, + { "png", "image/png" }, + { "ppm", "image/x-portable-pixmap" }, + { "rgb", "image/x-rgb" }, + { "tga", "image/x-targa" }, + { "tif", "image/tiff" }, + { "tiff", "image/tiff" }, + { "xbm", "image/x-xbitmap" }, + { "djvu", "image/x-djvu" }, + { "svg", "image/svg+xml" }, + { "ico", "image/vnd.microsoft.icon" }, + + { "doc", "application/msword" }, + { "xls", "application/vnd.ms-excel" }, + { "xls", "application/vnd.ms-excel" }, + { "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }, + { "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" }, + { "ppt", "application/vnd.ms-powerpoint" }, + { "pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation" }, + { "chm", "application/x-chm" }, + + { "txt", "text/plain" }, + { "xml", "text/plain" }, + { "htm", "text/html" }, + { "html", "text/html" }, + { "rtf", "text/rtf" }, + { "c", "text/x-source-code" }, + { "cc", "text/x-source-code" }, + { "c++", "text/x-source-code" }, + { "h", "text/x-source-code" }, + { "hh", "text/x-source-code" }, + { "hpp", "text/x-source-code" }, + { "cxx", "text/x-source-code" }, + { "cpp", "text/x-source-code" }, + { "S", "text/x-source-code" }, + { "java", "text/x-source-code" }, + { "ini", "text/plain" }, + { "inf", "text/plain" }, + + { "ttf", "application/x-truetype" }, + + { NULL, NULL } +}; + + +const char* kAttrMimeTypeName = "BEOS:TYPE"; + +static const char* kFailBackMime = "application/octet-stream"; +static const char* kDirectoryMime = "application/x-vnd.Be-directory"; + + +status_t +set_mime(const char** mime, const char* filename) +{ + struct ext_mime *p; + int32 namelen; + int32 ext_len; + *mime = NULL; + + if (filename == NULL) { + *mime = kDirectoryMime; + return B_NO_ERROR; + } + namelen = strlen(filename); + + for (p = mimes; p->extension; p++) { + ext_len = strlen(p->extension); + + if (namelen <= ext_len) + continue; + + if (filename[namelen-ext_len-1] != '.') + continue; + + if (!strcasecmp(filename + namelen - ext_len, p->extension)) + break; + } + if(p->mime == NULL) + *mime = kFailBackMime; + else + *mime = p->mime; + + return B_NO_ERROR; +} diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp index df8c883a91..1318096167 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp @@ -6,6 +6,7 @@ #include "FUSEVolume.h" #include +#include #include @@ -282,18 +283,22 @@ private: struct FUSEVolume::AttrCookie : RWLockable { public: - AttrCookie() + AttrCookie(const char* name) : fValue(NULL), - fSize(0) + fSize(0), + fType(0) { + _SetType(name); } - AttrCookie(const char* value) + AttrCookie(const char* name, const char* value) : fValue(strdup(value)), - fSize(strlen(value) + 1) + fSize(strlen(value) + 1), + fType(0) { + _SetType(name); } ~AttrCookie() @@ -306,6 +311,11 @@ public: return fValue != NULL; } + uint32 Type() const + { + return fType; + } + status_t Allocate(size_t size) { fValue = (char*)malloc(size); @@ -341,9 +351,19 @@ public: return fSize; } +private: + void _SetType(const char* name) + { + if (strcmp(name, kAttrMimeTypeName) == 0) + fType = B_MIME_STRING_TYPE; + else + fType = B_RAW_TYPE; + } + private: char* fValue; size_t fSize; + uint32 fType; }; @@ -2165,10 +2185,22 @@ FUSEVolume::OpenAttr(void* _node, const char* name, int openMode, locker.Unlock(); int attrSize = fuse_fs_getxattr(fFS, path, name, NULL, 0); - if (attrSize < 0) - return attrSize; + if (attrSize < 0) { + if (strcmp(name, kAttrMimeTypeName) == 0) { + // Return a fake MIME type attribute based on the file extension + const char* mimeType = NULL; + error = set_mime(&mimeType, S_ISDIR(node->type) ? NULL : &path[0]); + if (error != B_OK) + return error; + *_cookie = new(std::nothrow)AttrCookie(name, mimeType); + return B_OK; + } - AttrCookie* cookie = new(std::nothrow)AttrCookie(); + // Reading attribute failed + return attrSize; + } + + AttrCookie* cookie = new(std::nothrow)AttrCookie(name); error = cookie->Allocate(attrSize); if (error != B_OK) RETURN_ERROR(error); @@ -2227,7 +2259,7 @@ FUSEVolume::ReadAttrStat(void* _node, void* _cookie, struct stat* st) RETURN_ERROR(B_BAD_VALUE); st->st_size = cookie->Size(); - st->st_type = B_RAW_TYPE; + st->st_type = cookie->Type(); return B_OK; } diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/Jamfile b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/Jamfile index dff868228f..628ccdc3e6 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/Jamfile +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/Jamfile @@ -27,7 +27,10 @@ SharedLibrary libuserlandfs_fuse.so fuse_opt.c FUSEFileSystem.cpp FUSEVolume.cpp - + mime_ext_table.c : userlandfs_server shared be [ TargetLibsupc++ ] ; + +SEARCH on [ FGristFiles mime_ext_table.c ] + += [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;