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)
This commit is contained in:
parent
5285711417
commit
72cfe268ad
14 changed files with 106 additions and 19 deletions
|
@ -65,6 +65,7 @@ def _get_thumbnail_path(url):
|
||||||
# Icon names for some recoll mime types which don't have standard icon by the
|
# Icon names for some recoll mime types which don't have standard icon by the
|
||||||
# normal method
|
# normal method
|
||||||
SPEC_MIME_ICONS = {'application/x-fsdirectory' : 'gnome-fs-directory.svg',
|
SPEC_MIME_ICONS = {'application/x-fsdirectory' : 'gnome-fs-directory.svg',
|
||||||
|
'inode/directory' : 'gnome-fs-directory.svg',
|
||||||
'message/rfc822' : 'mail-read',
|
'message/rfc822' : 'mail-read',
|
||||||
'application/x-recoll' : 'recoll'}
|
'application/x-recoll' : 'recoll'}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
|
|
||||||
using std::string;
|
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://
|
// The url has to be like file://
|
||||||
if (idoc.url.find(cstr_fileu) != 0) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
fn = idoc.url.substr(7, string::npos);
|
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",
|
LOGERR(("FSDocFetcher::fetch: stat errno %d for [%s]\n",
|
||||||
errno, fn.c_str()));
|
errno, fn.c_str()));
|
||||||
return false;
|
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)
|
bool FSDocFetcher::fetch(RclConfig* cnf, const Rcl::Doc& idoc, RawDoc& out)
|
||||||
{
|
{
|
||||||
string fn;
|
string fn;
|
||||||
if (!urltopath(idoc, fn, out.st))
|
if (!urltopath(cnf, idoc, fn, out.st))
|
||||||
return false;
|
return false;
|
||||||
out.kind = RawDoc::RDK_FILENAME;
|
out.kind = RawDoc::RDK_FILENAME;
|
||||||
out.data = fn;
|
out.data = fn;
|
||||||
|
@ -62,7 +67,7 @@ bool FSDocFetcher::makesig(RclConfig* cnf, const Rcl::Doc& idoc, string& sig)
|
||||||
{
|
{
|
||||||
string fn;
|
string fn;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (!urltopath(idoc, fn, st))
|
if (!urltopath(cnf, idoc, fn, st))
|
||||||
return false;
|
return false;
|
||||||
FsIndexer::makesig(&st, sig);
|
FsIndexer::makesig(&st, sig);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
#ifndef _fsindexer_h_included_
|
#ifndef _fsindexer_h_included_
|
||||||
#define _fsindexer_h_included_
|
#define _fsindexer_h_included_
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include "indexer.h"
|
#include "indexer.h"
|
||||||
|
|
|
@ -122,9 +122,11 @@ string mimetype(const string &fn, const struct stat *stp,
|
||||||
// 'mime:' filter with the query language, but it's not work
|
// 'mime:' filter with the query language, but it's not work
|
||||||
// changing (would force a reindex).
|
// changing (would force a reindex).
|
||||||
if (S_ISDIR(stp->st_mode))
|
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))
|
if (!S_ISREG(stp->st_mode))
|
||||||
return "application/x-fsspecial";
|
return "inode/x-fsspecial";
|
||||||
}
|
}
|
||||||
|
|
||||||
string mtype;
|
string mtype;
|
||||||
|
@ -191,7 +193,7 @@ int main(int argc, const char **argv)
|
||||||
while (--argc > 0) {
|
while (--argc > 0) {
|
||||||
string filename = *++argv;
|
string filename = *++argv;
|
||||||
struct stat st;
|
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());
|
fprintf(stderr, "Can't stat %s\n", filename.c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
70
src/internfile/mh_symlink.h
Normal file
70
src/internfile/mh_symlink.h
Normal file
|
@ -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 <string>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#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_ */
|
|
@ -37,6 +37,7 @@ using namespace std;
|
||||||
#include "mh_mail.h"
|
#include "mh_mail.h"
|
||||||
#include "mh_mbox.h"
|
#include "mh_mbox.h"
|
||||||
#include "mh_text.h"
|
#include "mh_text.h"
|
||||||
|
#include "mh_symlink.h"
|
||||||
#include "mh_unknown.h"
|
#include "mh_unknown.h"
|
||||||
#include "ptmutex.h"
|
#include "ptmutex.h"
|
||||||
|
|
||||||
|
@ -148,6 +149,9 @@ static Dijon::Filter *mhFactory(RclConfig *config, const string &mime)
|
||||||
} else if ("message/rfc822" == lmime) {
|
} else if ("message/rfc822" == lmime) {
|
||||||
LOGDEB2(("mhFactory(%s): returning MimeHandlerMail\n", mime.c_str()));
|
LOGDEB2(("mhFactory(%s): returning MimeHandlerMail\n", mime.c_str()));
|
||||||
return new MimeHandlerMail(config, lmime);
|
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) {
|
} else if (lmime.find("text/") == 0) {
|
||||||
// Try to handle unknown text/xx as text/plain. This
|
// Try to handle unknown text/xx as text/plain. This
|
||||||
// only happen if the text/xx was defined as "internal" in
|
// only happen if the text/xx was defined as "internal" in
|
||||||
|
|
|
@ -102,7 +102,8 @@ static const UDSEntry resultToUDSEntry(const Rcl::Doc& doc, int num)
|
||||||
char cnum[30];sprintf(cnum, "%04d", num);
|
char cnum[30];sprintf(cnum, "%04d", num);
|
||||||
entry.insert(KIO::UDSEntry::UDS_NAME, resultBaseName + cnum);
|
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_MIME_TYPE, "inode/directory");
|
||||||
entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
|
entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
|
||||||
} else {
|
} else {
|
||||||
|
|
BIN
src/qtgui/mtpics/emblem-symbolic-link.png
Normal file
BIN
src/qtgui/mtpics/emblem-symbolic-link.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
|
@ -1019,7 +1019,7 @@ void ResList::menuPreviewParent()
|
||||||
// No parent doc: show enclosing folder with app configured for
|
// No parent doc: show enclosing folder with app configured for
|
||||||
// directories
|
// directories
|
||||||
pdoc.url = path_getfather(doc.url);
|
pdoc.url = path_getfather(doc.url);
|
||||||
pdoc.mimetype = "application/x-fsdirectory";
|
pdoc.mimetype = "inode/directory";
|
||||||
emit editRequested(pdoc);
|
emit editRequested(pdoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1038,7 +1038,7 @@ void ResList::menuOpenParent()
|
||||||
pdoc.url = path_getfather(doc.url);
|
pdoc.url = path_getfather(doc.url);
|
||||||
pdoc.meta[Rcl::Doc::keychildurl] = doc.url;
|
pdoc.meta[Rcl::Doc::keychildurl] = doc.url;
|
||||||
pdoc.meta[Rcl::Doc::keyapptg] = "parentopen";
|
pdoc.meta[Rcl::Doc::keyapptg] = "parentopen";
|
||||||
pdoc.mimetype = "application/x-fsdirectory";
|
pdoc.mimetype = "inode/directory";
|
||||||
emit editRequested(pdoc);
|
emit editRequested(pdoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -793,7 +793,7 @@ void ResTable::menuPreviewParent()
|
||||||
pdoc.url = path_getfather(doc.url);
|
pdoc.url = path_getfather(doc.url);
|
||||||
pdoc.meta[Rcl::Doc::keychildurl] = doc.url;
|
pdoc.meta[Rcl::Doc::keychildurl] = doc.url;
|
||||||
pdoc.meta[Rcl::Doc::keyapptg] = "parentopen";
|
pdoc.meta[Rcl::Doc::keyapptg] = "parentopen";
|
||||||
pdoc.mimetype = "application/x-fsdirectory";
|
pdoc.mimetype = "inode/directory";
|
||||||
emit editRequested(pdoc);
|
emit editRequested(pdoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -815,7 +815,7 @@ void ResTable::menuOpenParent()
|
||||||
pdoc.url = path_getfather(doc.url);
|
pdoc.url = path_getfather(doc.url);
|
||||||
pdoc.meta[Rcl::Doc::keychildurl] = doc.url;
|
pdoc.meta[Rcl::Doc::keychildurl] = doc.url;
|
||||||
pdoc.meta[Rcl::Doc::keyapptg] = "parentopen";
|
pdoc.meta[Rcl::Doc::keyapptg] = "parentopen";
|
||||||
pdoc.mimetype = "application/x-fsdirectory";
|
pdoc.mimetype = "inode/directory";
|
||||||
emit editRequested(pdoc);
|
emit editRequested(pdoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,7 @@ image/tiff = execm rclimg
|
||||||
image/vnd.djvu = exec rcldjvu
|
image/vnd.djvu = exec rcldjvu
|
||||||
image/svg+xml = exec rclsvg
|
image/svg+xml = exec rclsvg
|
||||||
image/x-xcf = execm rclimg
|
image/x-xcf = execm rclimg
|
||||||
|
inode/symlink = internal
|
||||||
message/rfc822 = internal
|
message/rfc822 = internal
|
||||||
text/calendar = execm rclics;mimetype=text/plain
|
text/calendar = execm rclics;mimetype=text/plain
|
||||||
text/html = internal
|
text/html = internal
|
||||||
|
@ -212,6 +213,8 @@ image/tiff = image
|
||||||
image/vnd.djvu = document
|
image/vnd.djvu = document
|
||||||
image/x-xcf = image
|
image/x-xcf = image
|
||||||
image/x-xpmi = image
|
image/x-xpmi = image
|
||||||
|
inode/directory = folder
|
||||||
|
inode/symlink = emblem-symbolic-link
|
||||||
message/rfc822 = message
|
message/rfc822 = message
|
||||||
text/html = html
|
text/html = html
|
||||||
text/html|chm = bookchap
|
text/html|chm = bookchap
|
||||||
|
@ -340,6 +343,8 @@ other = application/vnd.sun.xml.draw \
|
||||||
application/x-tar \
|
application/x-tar \
|
||||||
application/x-webarchive \
|
application/x-webarchive \
|
||||||
application/zip \
|
application/zip \
|
||||||
|
inode/directory \
|
||||||
|
inode/symlink \
|
||||||
|
|
||||||
[guifilters]
|
[guifilters]
|
||||||
# This defines the top level filters in the GUI (accessed by the the
|
# This defines the top level filters in the GUI (accessed by the the
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
# parent document instead of a temporary html file.
|
# parent document instead of a temporary html file.
|
||||||
xallexcepts = application/pdf application/postscript application/x-dvi \
|
xallexcepts = application/pdf application/postscript application/x-dvi \
|
||||||
text/html|gnuinfo text/html|chm text/html|epub \
|
text/html|gnuinfo text/html|chm text/html|epub \
|
||||||
application/x-fsdirectory|parentopen
|
application/x-fsdirectory|parentopen inode/directory|parentopen
|
||||||
|
|
||||||
[view]
|
[view]
|
||||||
# Pseudo entry used if the 'use desktop' preference is set in the GUI
|
# Pseudo entry used if the 'use desktop' preference is set in the GUI
|
||||||
|
@ -80,8 +80,9 @@ application/x-chm = kchmviewer %f
|
||||||
application/x-dia-diagram = dia %f
|
application/x-dia-diagram = dia %f
|
||||||
|
|
||||||
application/x-fsdirectory = dolphin %f
|
application/x-fsdirectory = dolphin %f
|
||||||
#application/x-fsdirectory|parentopen = nautilus %(childurl)
|
inode/directory = dolphin %f
|
||||||
application/x-fsdirectory|parentopen = dolphin --select %(childurl) %f
|
application/x-fsdirectory|parentopen = dolphin --select %(childurl) %f
|
||||||
|
inode/directory|parentopen = dolphin --select %(childurl) %f
|
||||||
|
|
||||||
application/x-gnuinfo = xterm -e "info -f %f"
|
application/x-gnuinfo = xterm -e "info -f %f"
|
||||||
application/x-gnumeric = gnumeric %f
|
application/x-gnumeric = gnumeric %f
|
||||||
|
|
|
@ -399,7 +399,7 @@ FsTreeWalker::Status FsTreeWalker::iwalk(const string &top,
|
||||||
if ((status = cb.processone(top, &st, FtwDirReturn))
|
if ((status = cb.processone(top, &st, FtwDirReturn))
|
||||||
& (FtwStop|FtwError))
|
& (FtwStop|FtwError))
|
||||||
goto out;
|
goto out;
|
||||||
} else if (S_ISREG(st.st_mode)) {
|
} else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
|
||||||
if ((status = cb.processone(fn, &st, FtwRegular)) &
|
if ((status = cb.processone(fn, &st, FtwRegular)) &
|
||||||
(FtwStop|FtwError)) {
|
(FtwStop|FtwError)) {
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -41,7 +41,7 @@ int wipedir(const string& dir, bool selfalso, bool recurse)
|
||||||
int statret;
|
int statret;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
statret = stat(dir.c_str(), &st);
|
statret = lstat(dir.c_str(), &st);
|
||||||
if (statret == -1) {
|
if (statret == -1) {
|
||||||
LOGERR(("wipedir: cant stat %s, errno %d\n", dir.c_str(), errno));
|
LOGERR(("wipedir: cant stat %s, errno %d\n", dir.c_str(), errno));
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -70,7 +70,7 @@ int wipedir(const string& dir, bool selfalso, bool recurse)
|
||||||
string fn = path_cat(dir, ent->d_name);
|
string fn = path_cat(dir, ent->d_name);
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int statret = stat(fn.c_str(), &st);
|
int statret = lstat(fn.c_str(), &st);
|
||||||
if (statret == -1) {
|
if (statret == -1) {
|
||||||
LOGERR(("wipedir: cant stat %s, errno %d\n", fn.c_str(), errno));
|
LOGERR(("wipedir: cant stat %s, errno %d\n", fn.c_str(), errno));
|
||||||
goto out;
|
goto out;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue