From 72cfe268ad685e96b1afeaf38b561b6e05446d9a Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Wed, 17 Apr 2013 18:34:02 +0200 Subject: [PATCH] Add support for indexing symlinks as such. Use inode/directory instead of application/x-fsdirectory as directory mime type. Fix stat/lstat usage in places (wipedir) --- .../recollscope/rclsearch.py | 1 + src/index/fsfetcher.cpp | 13 +++- src/index/fsindexer.h | 2 - src/index/mimetype.cpp | 8 +- src/internfile/mh_symlink.h | 70 ++++++++++++++++++ src/internfile/mimehandler.cpp | 4 + src/kde/kioslave/kio_recoll/dirif.cpp | 3 +- src/qtgui/mtpics/emblem-symbolic-link.png | Bin 0 -> 1891 bytes src/qtgui/reslist.cpp | 4 +- src/qtgui/restable.cpp | 4 +- src/sampleconf/mimeconf | 5 ++ src/sampleconf/mimeview | 5 +- src/utils/fstreewalk.cpp | 2 +- src/utils/wipedir.cpp | 4 +- 14 files changed, 106 insertions(+), 19 deletions(-) create mode 100644 src/internfile/mh_symlink.h create mode 100644 src/qtgui/mtpics/emblem-symbolic-link.png diff --git a/src/desktop/unity-lens-recoll/recollscope/rclsearch.py b/src/desktop/unity-lens-recoll/recollscope/rclsearch.py index 50caec4a..ae4766d2 100755 --- a/src/desktop/unity-lens-recoll/recollscope/rclsearch.py +++ b/src/desktop/unity-lens-recoll/recollscope/rclsearch.py @@ -65,6 +65,7 @@ def _get_thumbnail_path(url): # Icon names for some recoll mime types which don't have standard icon by the # normal method SPEC_MIME_ICONS = {'application/x-fsdirectory' : 'gnome-fs-directory.svg', + 'inode/directory' : 'gnome-fs-directory.svg', 'message/rfc822' : 'mail-read', 'application/x-recoll' : 'recoll'} diff --git a/src/index/fsfetcher.cpp b/src/index/fsfetcher.cpp index cc809d86..f1dc6f13 100644 --- a/src/index/fsfetcher.cpp +++ b/src/index/fsfetcher.cpp @@ -31,7 +31,8 @@ using std::string; -static bool urltopath(const Rcl::Doc& idoc, string& fn, struct stat& st) +static bool urltopath(RclConfig* cnf, + const Rcl::Doc& idoc, string& fn, struct stat& st) { // The url has to be like file:// if (idoc.url.find(cstr_fileu) != 0) { @@ -40,7 +41,11 @@ static bool urltopath(const Rcl::Doc& idoc, string& fn, struct stat& st) return false; } fn = idoc.url.substr(7, string::npos); - if (stat(fn.c_str(), &st) < 0) { + cnf->setKeyDir(path_getfather(fn)); + bool follow = false; + cnf->getConfParam("followLinks", &follow); + + if ((follow ? stat(fn.c_str(), &st) : lstat(fn.c_str(), &st))< 0) { LOGERR(("FSDocFetcher::fetch: stat errno %d for [%s]\n", errno, fn.c_str())); return false; @@ -51,7 +56,7 @@ static bool urltopath(const Rcl::Doc& idoc, string& fn, struct stat& st) bool FSDocFetcher::fetch(RclConfig* cnf, const Rcl::Doc& idoc, RawDoc& out) { string fn; - if (!urltopath(idoc, fn, out.st)) + if (!urltopath(cnf, idoc, fn, out.st)) return false; out.kind = RawDoc::RDK_FILENAME; out.data = fn; @@ -62,7 +67,7 @@ bool FSDocFetcher::makesig(RclConfig* cnf, const Rcl::Doc& idoc, string& sig) { string fn; struct stat st; - if (!urltopath(idoc, fn, st)) + if (!urltopath(cnf, idoc, fn, st)) return false; FsIndexer::makesig(&st, sig); return true; diff --git a/src/index/fsindexer.h b/src/index/fsindexer.h index 37dd0798..ad561562 100644 --- a/src/index/fsindexer.h +++ b/src/index/fsindexer.h @@ -17,8 +17,6 @@ #ifndef _fsindexer_h_included_ #define _fsindexer_h_included_ -#include - #include #include "indexer.h" diff --git a/src/index/mimetype.cpp b/src/index/mimetype.cpp index 508a4385..be4c8999 100644 --- a/src/index/mimetype.cpp +++ b/src/index/mimetype.cpp @@ -122,9 +122,11 @@ string mimetype(const string &fn, const struct stat *stp, // 'mime:' filter with the query language, but it's not work // changing (would force a reindex). if (S_ISDIR(stp->st_mode)) - return "application/x-fsdirectory"; + return "inode/directory"; + if (S_ISLNK(stp->st_mode)) + return "inode/symlink"; if (!S_ISREG(stp->st_mode)) - return "application/x-fsspecial"; + return "inode/x-fsspecial"; } string mtype; @@ -191,7 +193,7 @@ int main(int argc, const char **argv) while (--argc > 0) { string filename = *++argv; struct stat st; - if (stat(filename.c_str(), &st)) { + if (lstat(filename.c_str(), &st)) { fprintf(stderr, "Can't stat %s\n", filename.c_str()); continue; } diff --git a/src/internfile/mh_symlink.h b/src/internfile/mh_symlink.h new file mode 100644 index 00000000..8ce2dbea --- /dev/null +++ b/src/internfile/mh_symlink.h @@ -0,0 +1,70 @@ +/* Copyright (C) 2004 J.F.Dockes + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef _MH_SYMLINK_H_INCLUDED_ +#define _MH_SYMLINK_H_INCLUDED_ + +#include +#include +#include + +#include "cstr.h" +#include "mimehandler.h" +#include "transcode.h" +#include "pathut.h" +#include "debuglog.h" + +/** Index symlink target + * + * Not sure that this is such a good idea, so it's disabled by default in + * the config. Add inode/symlink = internal to the index section of mimeconf + * to enable. + */ +class MimeHandlerSymlink : public RecollFilter { + public: + MimeHandlerSymlink(RclConfig *cnf, const std::string& mt) + : RecollFilter(cnf, mt) {} + virtual ~MimeHandlerSymlink() {} + virtual bool set_document_file(const string& fn) + { + RecollFilter::set_document_file(fn); + m_fn = fn; + return m_havedoc = true; + } + virtual bool next_document() + { + if (m_havedoc == false) + return false; + m_havedoc = false; + m_metaData[cstr_dj_keycontent] = cstr_null; + char lc[1024]; + ssize_t bytes = readlink(m_fn.c_str(), lc, 1024); + if (bytes != (ssize_t)-1) { + string slc(lc, bytes); + transcode(path_getsimple(slc), m_metaData[cstr_dj_keycontent], + m_config->getDefCharset(true), "UTF-8"); + } else { + LOGDEB(("Symlink: readlink [%s] failed, errno %d\n", m_fn.c_str(), + errno)); + } + m_metaData[cstr_dj_keymt] = cstr_textplain; + return true; + } +private: + std::string m_fn; +}; + +#endif /* _MH_SYMLINK_H_INCLUDED_ */ diff --git a/src/internfile/mimehandler.cpp b/src/internfile/mimehandler.cpp index 61a9d514..5f33e759 100644 --- a/src/internfile/mimehandler.cpp +++ b/src/internfile/mimehandler.cpp @@ -37,6 +37,7 @@ using namespace std; #include "mh_mail.h" #include "mh_mbox.h" #include "mh_text.h" +#include "mh_symlink.h" #include "mh_unknown.h" #include "ptmutex.h" @@ -148,6 +149,9 @@ static Dijon::Filter *mhFactory(RclConfig *config, const string &mime) } else if ("message/rfc822" == lmime) { LOGDEB2(("mhFactory(%s): returning MimeHandlerMail\n", mime.c_str())); return new MimeHandlerMail(config, lmime); + } else if ("inode/symlink" == lmime) { + LOGDEB2(("mhFactory(%s): ret MimeHandlerSymlink\n", mime.c_str())); + return new MimeHandlerSymlink(config, lmime); } else if (lmime.find("text/") == 0) { // Try to handle unknown text/xx as text/plain. This // only happen if the text/xx was defined as "internal" in diff --git a/src/kde/kioslave/kio_recoll/dirif.cpp b/src/kde/kioslave/kio_recoll/dirif.cpp index 29afe7fb..447e7f7b 100644 --- a/src/kde/kioslave/kio_recoll/dirif.cpp +++ b/src/kde/kioslave/kio_recoll/dirif.cpp @@ -102,7 +102,8 @@ static const UDSEntry resultToUDSEntry(const Rcl::Doc& doc, int num) char cnum[30];sprintf(cnum, "%04d", num); entry.insert(KIO::UDSEntry::UDS_NAME, resultBaseName + cnum); - if (!doc.mimetype.compare("application/x-fsdirectory")) { + if (!doc.mimetype.compare("application/x-fsdirectory") || + !doc.mimetype.compare("inode/directory")) { entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "inode/directory"); entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); } else { diff --git a/src/qtgui/mtpics/emblem-symbolic-link.png b/src/qtgui/mtpics/emblem-symbolic-link.png new file mode 100644 index 0000000000000000000000000000000000000000..9f35b79e7724f13dc8d5ac6b326ac8b1b28e8fe4 GIT binary patch literal 1891 zcmV-p2b}ncP)o3 zA<-7(h;6CJe}E`QtVEO=!B`%UPa~{q!b%xj)!Tcg z>dEwz6`V8RoQJ`58Ej|Vciwa(K?s4+rKGwKrd?7!jPml8&o*z`G_v#CT_a^>WyuI9 zvy9dOsb0|8d8O)R*Uef@CdGTRXfO-&Iue2iGI}tn+9U#^Afr2a{CH|b7mi6{``(tl z!DYeMt6_G&oXeA^cM7} z1Cz|utq7F29JnGT$PqfkC6xp)7JNVPQV5}sU7J>7L6P3J0GcRsUUmb}Vax^BZQPI- zSW>PbTS3IRn*)LhNH9c%aO8z>A_$j0A@VvO;t_xVLX(t|`^j@%2dp!q&U7i6@wyUF z(T@-y<3r#%uyrQ1m+8-jJV%%`pnoBA-ZX>=P5|4N zup$U6f^CaI07stkl+zhJ=2`?gGQ^si641D(336rIzy8V!5G)aDJaI*UBhR@LfpLxn zmPUX}mpW8RHa6x&gfMZ0bmVOrM+8tONS@K;W<_v0%@D|2l^vHZs&H;Lv> zU_~)v#1a8!RtL&wRUy(G7^%9h2-gFRkga*17rj~(Zn1=AOc4Oa>&%3Gr1u#S zC**P+kP7h#K-Xh#2uFKgr^lK#Yhd5L{opL?2yl0TAfuunz6g+-Y{2{A6Jbxo9w;d( zfn1r;b3lMR#2*2|^9<2wfDvQEhA#mvw-ErEG`#Z^2okmcP-SUZ8PwF&!0XtR!Aj*y%KL(?tqrkwK1ZU^Yom1~|{P>UlIUw+%3FIIG z_?uh>C<;7+M-U3a)8}mc#*LpL%7%u9;MT2M`uPrlV*zK+o`u%dR-f>~_9r}7Cz!qk z;;jo{2PgH}6Mpx3{1Ax_W7El^q@)F6 z+p%NE2rN=_V+-@hXcA2If&&K*s7|`Nx~e87CRQvK&l7n&w)C9RZs{ zx89EB=|;(QrKP3Uu-c8dk6dR%DUfE%`8*lqshP18h>Of*4iIL){Uq(Wrj5stXGUYD zu@eWwMP!l!%dq$e@x^&q4<6J!36T0FZ^U?0Raj>nkp=X3j!1b dCd_name); struct stat st; - int statret = stat(fn.c_str(), &st); + int statret = lstat(fn.c_str(), &st); if (statret == -1) { LOGERR(("wipedir: cant stat %s, errno %d\n", fn.c_str(), errno)); goto out;