1 /* fileentry.cc
2  * This file belongs to Worker, a file manager for UN*X/X11.
3  * Copyright (C) 2001-2020 Ralf Hoffmann.
4  * You can contact me at: ralf@boomerangsworld.de
5  *   or http://www.boomerangsworld.de/worker
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #include "fileentry.hh"
23 #include "aguix/lowlevelfunc.h"
24 #include "aguix/fieldlistviewdnd.h"
25 #include "wconfig.h"
26 #include "grouphash.h"
27 #include "pdatei.h"
28 #include "nmrowdata.h"
29 #include "condparser.h"
30 #include "stringbuf.h"
31 #include "wcfiletype.hh"
32 #include "magic_db.hh"
33 #include "worker.h"
34 #include "nwc_os.hh"
35 
36 class FEBookmarkInfo {
37 public:
FEBookmarkInfo()38     FEBookmarkInfo() : m_bookmark_match( FileEntry::NOT_IN_BOOKMARKS ),
39                        m_matching_labels( NULL )
40     {
41     }
FEBookmarkInfo(const FEBookmarkInfo & other)42     FEBookmarkInfo( const FEBookmarkInfo &other ) : m_bookmark_match( other.m_bookmark_match ),
43                                                     m_matching_labels( NULL )
44     {
45         if ( other.m_matching_labels != NULL ) {
46             m_matching_labels = new std::list<std::string>( *other.m_matching_labels );
47         }
48     }
49 
~FEBookmarkInfo()50     ~FEBookmarkInfo()
51     {
52         if ( m_matching_labels != NULL ) {
53             delete m_matching_labels;
54         }
55     }
56 
operator =(const FEBookmarkInfo & rhs)57     FEBookmarkInfo &operator=( const FEBookmarkInfo &rhs )
58     {
59         if ( this != &rhs ) {
60             m_bookmark_match = rhs.m_bookmark_match;
61 
62             if ( m_matching_labels != NULL ) delete m_matching_labels;
63             if ( rhs.m_matching_labels != NULL ) {
64                 m_matching_labels = new std::list<std::string>( *rhs.m_matching_labels );
65             } else {
66                 m_matching_labels = NULL;
67             }
68         }
69         return *this;
70     }
71 
72 
73     FileEntry::bookmark_match_t m_bookmark_match;
74     std::list<std::string> *m_matching_labels;
75 };
76 
FileEntry()77 FileEntry::FileEntry()
78 {
79   name=NULL;
80   fullname=NULL;
81   filetype=NULL;
82   use=true;
83   isHidden=false;
84   isCorrupt = false;
85 
86   reclistQueued = false;
87 
88   memset( &statbuf, 0, sizeof( statbuf ) );
89   memset( &dstatbuf, 0, sizeof( dstatbuf ) );
90 
91   contentBuf.content = NULL;
92   contentBuf.size = 0;
93 
94   outputBuf = NULL;
95 
96   _ID = -1;
97 
98   m_bookmark_info = NULL;
99 }
100 
~FileEntry()101 FileEntry::~FileEntry()
102 {
103   if(name!=NULL) _freesafe(name);
104   if(fullname!=NULL) _freesafe(fullname);
105   freeContentBuf();
106   freeOutputBuf();
107 
108   if ( m_bookmark_info != NULL ) delete m_bookmark_info;
109 }
110 
isDir() const111 bool FileEntry::isDir() const
112 {
113   bool dir=false;
114   if ( isLink == true ) {
115     if ( isCorrupt == false ) {
116       if ( S_ISDIR( dstatbuf.mode ) ) dir = true;
117     }
118   } else if ( S_ISDIR( statbuf.mode ) ) dir = true;
119   return dir;
120 }
121 
duplicate()122 FileEntry *FileEntry::duplicate()
123 {
124 #if 0
125   FileEntry *tfe=new FileEntry();
126   tfe->fullname=dupstring(fullname);
127   tfe->name=dupstring(name);
128   tfe->dirsize=dirsize;
129   tfe->select=select;
130   tfe->isLink=isLink;
131   tfe->isCorrupt=isCorrupt;
132   tfe->inFilter=inFilter;
133   tfe->filetype=filetype;
134 
135   memcpy( &( tfe->statbuf ), &statbuf, sizeof( statbuf ) );
136   memcpy( &( tfe->dstatbuf ), &dstatbuf, sizeof( dstatbuf ) );
137 
138   tfe->setCustomColors( customcolors );
139   tfe->setColor( 0, fg );
140   tfe->setColor( 1, bg );
141 
142   return tfe;
143 #endif
144   return new FileEntry( *this );
145 }
146 
readInfos()147 int FileEntry::readInfos()
148 {
149   return readInfos(false);
150 }
151 
readInfos(bool update)152 int FileEntry::readInfos( bool update )
153 {
154     //TODO: auf update achten
155     worker_struct_stat stbuf;
156 
157     select = false;
158     dirsize = -1;
159     filetype = NULL;
160     isCorrupt = false;
161     isLink = false;
162 
163     if ( fullname == NULL ) return 1;
164 
165     memset( &statbuf, 0, sizeof( statbuf ) );
166     memset( &dstatbuf, 0, sizeof( dstatbuf ) );
167 
168     if ( worker_lstat( fullname, &stbuf ) == 0 ) {
169         statbuf.size = stbuf.st_size;
170         statbuf.lastaccess = stbuf.st_atime;
171         statbuf.lastmod = stbuf.st_mtime;
172         statbuf.lastchange = stbuf.st_ctime;
173         statbuf.mode = stbuf.st_mode;
174         statbuf.userid = stbuf.st_uid;
175         statbuf.groupid = stbuf.st_gid;
176         statbuf.inode = stbuf.st_ino;
177         statbuf.nlink = stbuf.st_nlink;
178         statbuf.blocks = stbuf.st_blocks;
179         statbuf.rdev = stbuf.st_rdev;
180         statbuf.dev = stbuf.st_dev;
181     } else {
182         isCorrupt = true;
183         return 2;
184     }
185 
186     if ( S_ISLNK( statbuf.mode ) ) {
187         isLink = true;
188         if ( worker_stat( fullname, &stbuf ) == 0 ) {
189             dstatbuf.size = stbuf.st_size;
190             dstatbuf.lastaccess = stbuf.st_atime;
191             dstatbuf.lastmod = stbuf.st_mtime;
192             dstatbuf.lastchange = stbuf.st_ctime;
193             dstatbuf.mode = stbuf.st_mode;
194             dstatbuf.userid = stbuf.st_uid;
195             dstatbuf.groupid = stbuf.st_gid;
196             dstatbuf.inode = stbuf.st_ino;
197             dstatbuf.nlink = stbuf.st_nlink;
198             dstatbuf.blocks = stbuf.st_blocks;
199             dstatbuf.rdev = stbuf.st_rdev;
200             dstatbuf.dev = stbuf.st_dev;
201         } else {
202             /* corrupt link */
203             isCorrupt = true;
204             dstatbuf.mode = 0;  // to prevent corrupt links treated as dirs
205             if ( errno == ENOENT ) {
206                 // Eventl. fuer spaetere Betrachtungen
207             }
208         }
209     }
210     return 0;
211 }
212 
getDestination() const213 char *FileEntry::getDestination() const
214 {
215     char *str = NULL;
216     if ( isLink == true && fullname != NULL ) {
217         str = NWC::OS::getLinkTarget( fullname );
218     }
219     return str;
220 }
221 
getPermissionString()222 const char *FileEntry::getPermissionString()
223 {
224   static char str[WORKER_PERMCHARS + 1];
225 
226   if ( isLink == true ) str[0] = 'l';
227   else {
228       if ( isCorrupt ) str[0] = '?';
229       else if ( S_ISDIR( statbuf.mode ) ) str[0] = 'd';
230       else if ( S_ISFIFO( statbuf.mode ) ) str[0] = 'p';
231       else if ( S_ISSOCK( statbuf.mode ) ) str[0] = 's';
232       else if ( S_ISCHR( statbuf.mode ) ) str[0] = 'c';
233       else if ( S_ISBLK( statbuf.mode ) ) str[0] = 'b';
234       else str[0] = '-';
235   }
236   if ( ( statbuf.mode & S_IRUSR ) == S_IRUSR ) str[1] = 'r'; else str[1] = '-';
237   if ( ( statbuf.mode & S_IWUSR ) == S_IWUSR ) str[2] = 'w'; else str[2] = '-';
238   if ( ( statbuf.mode & S_ISUID ) == S_ISUID ) {
239     if ( ( statbuf.mode & S_IXUSR ) == S_IXUSR ) str[3] = 's'; else str[3] = 'S';
240   } else {
241     if ( ( statbuf.mode & S_IXUSR ) == S_IXUSR ) str[3] = 'x'; else str[3] = '-';
242   }
243   if ( ( statbuf.mode & S_IRGRP ) == S_IRGRP ) str[4] = 'r'; else str[4] = '-';
244   if ( ( statbuf.mode & S_IWGRP ) == S_IWGRP ) str[5] = 'w'; else str[5] = '-';
245   if ( ( statbuf.mode & S_ISGID ) == S_ISGID ) {
246     if ( ( statbuf.mode & S_IXGRP ) == S_IXGRP ) str[6] = 's'; else str[6] = 'S';
247   } else {
248     if ( ( statbuf.mode & S_IXGRP ) == S_IXGRP ) str[6] = 'x'; else str[6] = '-';
249   }
250   if ( ( statbuf.mode & S_IROTH ) == S_IROTH ) str[7] = 'r'; else str[7] = '-';
251   if ( ( statbuf.mode & S_IWOTH ) == S_IWOTH ) str[8] = 'w'; else str[8] = '-';
252   if ( ( statbuf.mode & S_ISVTX ) == S_ISVTX ) {
253     if ( ( statbuf.mode & S_IXOTH ) == S_IXOTH ) str[9] = 't'; else str[9] = 'T';
254   } else {
255     if ( ( statbuf.mode & S_IXOTH ) == S_IXOTH ) str[9] = 'x'; else str[9] = '-';
256   }
257   str[10]=0;
258   return str;
259 }
260 
isExe(bool fastTest) const261 bool FileEntry::isExe( bool fastTest ) const
262 {
263   if ( fastTest == true ) {
264     if ( ( statbuf.mode & S_IXUSR ) == S_IXUSR ) return true;
265     if ( ( statbuf.mode & S_IXGRP ) == S_IXGRP ) return true;
266     if ( ( statbuf.mode & S_IXOTH ) == S_IXOTH ) return true;
267   } else {
268     uid_t uid;
269     gid_t gid;
270     mode_t m;
271     bool e = false;
272 
273     if ( isLink == false ) {
274       uid = userid();
275       gid = groupid();
276       m = mode();
277     } else if ( isCorrupt == false ) {
278       uid = duserid();
279       gid = dgroupid();
280       m = dmode();
281     } else {
282       // corrupt symlink is not executable
283       return false;
284     }
285 
286     if ( uid == geteuid() ) {
287       e = ( ( m & S_IXUSR ) != 0 ) ? true : false;
288     } else if ( ugdb->isInGroup( gid ) == true ) {
289       e = ( ( m & S_IXGRP ) != 0 ) ? true : false;
290     } else {
291       e = ( ( m & S_IXOTH ) != 0 ) ? true : false;
292     }
293     return e;
294   }
295   return false;
296 }
297 
match(const char * pattern)298 bool FileEntry::match( const char* pattern )
299 {
300   if(fnmatch(pattern,name,0)==0) return true;
301   return false;
302 }
303 
size() const304 loff_t FileEntry::size() const
305 {
306   return statbuf.size;
307 }
308 
lastaccess() const309 time_t FileEntry::lastaccess() const
310 {
311   return statbuf.lastaccess;
312 }
313 
lastmod() const314 time_t FileEntry::lastmod() const
315 {
316   return statbuf.lastmod;
317 }
318 
lastchange() const319 time_t FileEntry::lastchange() const
320 {
321   return statbuf.lastchange;
322 }
323 
mode() const324 mode_t FileEntry::mode() const
325 {
326   return statbuf.mode;
327 }
328 
userid() const329 uid_t FileEntry::userid() const
330 {
331   return statbuf.userid;
332 }
333 
groupid() const334 gid_t FileEntry::groupid() const
335 {
336   return statbuf.groupid;
337 }
338 
inode() const339 ino_t FileEntry::inode() const
340 {
341   return statbuf.inode;
342 }
343 
nlink() const344 nlink_t FileEntry::nlink() const
345 {
346   return statbuf.nlink;
347 }
348 
blocks() const349 loff_t FileEntry::blocks() const
350 {
351   return statbuf.blocks;
352 }
353 
dsize() const354 loff_t FileEntry::dsize() const
355 {
356   return dstatbuf.size;
357 }
358 
dlastaccess() const359 time_t FileEntry::dlastaccess() const
360 {
361   return dstatbuf.lastaccess;
362 }
363 
dlastmod() const364 time_t FileEntry::dlastmod() const
365 {
366   return dstatbuf.lastmod;
367 }
368 
dlastchange() const369 time_t FileEntry::dlastchange() const
370 {
371   return dstatbuf.lastchange;
372 }
373 
dmode() const374 mode_t FileEntry::dmode() const
375 {
376   return dstatbuf.mode;
377 }
378 
duserid() const379 uid_t FileEntry::duserid() const
380 {
381   return dstatbuf.userid;
382 }
383 
dgroupid() const384 gid_t FileEntry::dgroupid() const
385 {
386   return dstatbuf.groupid;
387 }
388 
dinode() const389 ino_t FileEntry::dinode() const
390 {
391   return dstatbuf.inode;
392 }
393 
dnlink() const394 nlink_t FileEntry::dnlink() const
395 {
396   return dstatbuf.nlink;
397 }
398 
dblocks() const399 loff_t FileEntry::dblocks() const
400 {
401   return dstatbuf.blocks;
402 }
403 
rdev() const404 dev_t FileEntry::rdev() const
405 {
406   return statbuf.rdev;
407 }
408 
drdev() const409 dev_t FileEntry::drdev() const
410 {
411   return dstatbuf.rdev;
412 }
413 
dev() const414 dev_t FileEntry::dev() const
415 {
416   return statbuf.dev;
417 }
418 
ddev() const419 dev_t FileEntry::ddev() const
420 {
421   return dstatbuf.dev;
422 }
423 
checkAccess(int m) const424 bool FileEntry::checkAccess( int m ) const
425 {
426   if ( fullname == NULL ) return false;
427   return ( worker_access( fullname, m ) == 0 ) ? true : false;
428 }
429 
getContentStr(int pos,int len)430 char *FileEntry::getContentStr( int pos, int len )
431 {
432   char *resstr = NULL;
433   int mylen, i;
434 
435   if ( pos < 0 ) return dupstring( "" );
436   if ( len < 1 ) return dupstring( "" );
437 
438   if ( contentBuf.content == NULL ) readContentBuf();
439   if ( contentBuf.content != NULL ) {
440     mylen = a_min( len, contentBuf.size - pos );
441     if ( mylen > 0 ) {
442       resstr = (char*)_allocsafe( mylen + 1 );
443       for ( i = 0; i < mylen; i++ ) {
444         resstr[i] = contentBuf.content[i+pos];
445       }
446       resstr[i] = '\0';
447     }
448   }
449 
450   return ( resstr != NULL ) ? resstr : dupstring( "" );
451 }
452 
getContentNum(int pos,int len)453 int FileEntry::getContentNum( int pos, int len )
454 {
455   int mylen, i;
456   int res = -1;
457 
458   if ( pos < 0 ) return -1;
459   if ( len < 1 ) return -1;
460 
461   if ( contentBuf.content == NULL ) readContentBuf();
462   if ( contentBuf.content != NULL ) {
463     mylen = a_min( len, contentBuf.size - pos );
464     if ( mylen > 0 ) {
465       res = 0;
466       for ( i = 0; i < mylen; i++ ) {
467         res <<= 8;
468         res += (unsigned char)contentBuf.content[i+pos];
469       }
470     }
471   }
472 
473   return res;
474 }
475 
freeContentBuf()476 void FileEntry::freeContentBuf()
477 {
478   if ( contentBuf.content != NULL ) {
479     _freesafe( contentBuf.content );
480     contentBuf.content = NULL;
481     contentBuf.size = 0;
482   }
483 }
484 
readContentBuf(int len)485 void FileEntry::readContentBuf( int len )
486 {
487   int reads, i;
488   unsigned char fbuffer[64];
489   PDatei *pfp;
490 
491   if ( isReg() == false ) return;
492   if ( ( len < 1 ) || ( len > 64 ) ) return;
493   if ( contentBuf.content == NULL ) {
494     reads = -1;
495     pfp = new PDatei();
496     if ( pfp->open( fullname ) == 0 ) {
497       reads = pfp->read( fbuffer, len );
498     }
499     delete pfp;
500     if ( ( reads > 0 ) && ( reads <= len ) ) {
501       contentBuf.content = (char*)_allocsafe( len + 1 );
502       contentBuf.size = reads;
503       for ( i = 0; i < reads; i++ ) {
504         contentBuf.content[i] = (char)fbuffer[i];
505       }
506       for ( i = reads; i < ( len + 1 ); i++ ) {
507         contentBuf.content[i] = '\0';
508       }
509     }
510   }
511 }
512 
freeOutputBuf()513 void FileEntry::freeOutputBuf()
514 {
515   if ( outputBuf != NULL ) {
516     delete outputBuf;
517     outputBuf = NULL;
518   }
519 }
520 
findOutput(const char * tcommand)521 const char *FileEntry::findOutput( const char *tcommand )
522 {
523   if ( outputBuf == NULL ) {
524     outputBuf = new StringBuf();
525   } else {
526     return outputBuf->find( tcommand );
527   }
528   return NULL;
529 }
530 
addOutput(const char * tcommand,const char * toutput,int value)531 void FileEntry::addOutput( const char *tcommand, const char *toutput, int value )
532 {
533   if ( outputBuf == NULL ) outputBuf = new StringBuf();
534 
535   outputBuf->add( tcommand, toutput, value );
536 }
537 
findReturnvalue(const char * tcommand,int * return_value)538 int FileEntry::findReturnvalue( const char *tcommand, int *return_value )
539 {
540   if ( outputBuf == NULL ) {
541     outputBuf = new StringBuf();
542   } else {
543     return outputBuf->findValue( tcommand, return_value );
544   }
545   return -1;
546 }
547 
findOutputAndRV(const char * tcommand,const char ** return_output,int * return_value)548 int FileEntry::findOutputAndRV( const char *tcommand,
549                                 const char **return_output,
550                                 int *return_value )
551 {
552   if ( outputBuf == NULL ) {
553     outputBuf = new StringBuf();
554   } else {
555     return outputBuf->find( tcommand, return_output, return_value );
556   }
557   return -1;
558 }
559 
isReg() const560 bool FileEntry::isReg() const
561 {
562   if ( isLink == false ) {
563     if ( isCorrupt == true ) return false;
564     if ( S_ISREG( statbuf.mode ) ) return true;
565     else return false;
566   }
567   if ( isCorrupt == true ) return false;
568   if ( S_ISREG( dstatbuf.mode ) ) return true;
569   return false;
570 }
571 
setCustomColor(const FileEntryCustomColor & c)572 void FileEntry::setCustomColor( const FileEntryCustomColor &c )
573 {
574     m_colors.setCustomColor( c );
575 }
576 
setCustomColors(const int fg[4],const int bg[4])577 void FileEntry::setCustomColors( const int fg[4], const int bg[4] )
578 {
579     m_colors.setCustomColors( fg, bg );
580 }
581 
getCustomColor() const582 const FileEntryCustomColor &FileEntry::getCustomColor() const
583 {
584     return m_colors.getCustomColor();
585 }
586 
getCustomColorSet() const587 int FileEntry::getCustomColorSet() const
588 {
589     return m_colors.getCustomColorSet();
590 }
591 
clearCustomColor()592 void FileEntry::clearCustomColor()
593 {
594     m_colors.setCustomColorSet( 0 );
595 }
596 
clearOverrideColor()597 void FileEntry::clearOverrideColor()
598 {
599     m_colors.setOverrideColorSet( 0 );
600 }
601 
setColor(const FileEntryColor & c)602 void FileEntry::setColor( const FileEntryColor &c )
603 {
604     m_colors = c;
605 }
606 
getColor() const607 const FileEntryColor &FileEntry::getColor() const
608 {
609     return m_colors;
610 }
611 
setOverrideColor(int type,int fg,int bg)612 void FileEntry::setOverrideColor( int type, int fg, int bg )
613 {
614     m_colors.setOverrideColor( type, fg, bg );
615 }
616 
617 /*
618  * Method to check for same destination file
619  * it currently only check the destination itself, not the possible
620  * destination of a symlink
621  */
isSameFile(const char * othername,bool follow_symlinks) const622 bool FileEntry::isSameFile( const char *othername, bool follow_symlinks ) const
623 {
624   worker_struct_stat buf;
625 
626   if ( othername == NULL ) return false;
627   if ( worker_stat( othername, &buf ) != 0 ) return false;
628 
629   if ( ( isLink == true ) && ( follow_symlinks == true ) && ( isCorrupt == false ) ) {
630     if ( ( dinode() == buf.st_ino ) && ( ddev() == buf.st_dev ) ) return true;
631   } else {
632     if ( ( inode() == buf.st_ino ) && ( dev() == buf.st_dev ) ) return true;
633   }
634   return false;
635 }
636 
FileEntry(const FileEntry & other)637 FileEntry::FileEntry( const FileEntry &other )
638 {
639   fullname = ( other.fullname != NULL ) ? dupstring( other.fullname ) : NULL;
640   name = (other.name != NULL ) ? dupstring( other.name ) : NULL;
641   filetype = other.filetype;
642   use = other.use;
643   isHidden = other.isHidden;
644   reclistQueued = other.reclistQueued;
645 
646   memcpy( &statbuf, &( other.statbuf ), sizeof( statbuf ) );
647   memcpy( &dstatbuf, &( other.dstatbuf ), sizeof( dstatbuf ) );
648 
649   setColor( other.getColor() );
650 
651   dirsize = other.dirsize;
652   select = other.select;
653   isLink = other.isLink;
654   isCorrupt = other.isCorrupt;
655 
656   // not copied
657   contentBuf.content = NULL;
658   contentBuf.size = 0;
659 
660   outputBuf = NULL;
661 
662   _ID = other._ID;
663 
664   if ( other.m_bookmark_info != NULL ) {
665       m_bookmark_info = new FEBookmarkInfo( *other.m_bookmark_info );
666   } else {
667       m_bookmark_info = NULL;
668   }
669 
670   m_filetype_file_output = other.m_filetype_file_output;
671   m_mime_type = other.m_mime_type;
672 }
673 
FileEntry(const NWC::FSEntry & other)674 FileEntry::FileEntry( const NWC::FSEntry &other )
675 {
676     fullname = dupstring( other.getFullname().c_str() );
677     name = dupstring( other.getBasename().c_str() );
678     filetype = nullptr;
679     use = true;
680     isHidden = other.isHiddenEntry();
681     isCorrupt = other.isBrokenLink();
682 
683     reclistQueued = false;
684 
685     memset( &statbuf, 0, sizeof( statbuf ) );
686     memset( &dstatbuf, 0, sizeof( dstatbuf ) );
687 
688     statbuf.size = other.stat_size();
689     statbuf.lastaccess = other.stat_lastaccess();
690     statbuf.lastmod = other.stat_lastmod();
691     statbuf.lastchange = other.stat_lastchange();
692     statbuf.mode = other.stat_mode();
693     statbuf.userid = other.stat_userid();
694     statbuf.groupid = other.stat_groupid();
695     statbuf.inode = other.stat_inode();
696     statbuf.nlink = other.stat_nlink();
697     statbuf.blocks = other.stat_blocks();
698     statbuf.rdev = other.stat_rdev();
699     statbuf.dev = other.stat_dev();
700 
701     dstatbuf.size = other.stat_dest_size();
702     dstatbuf.lastaccess = other.stat_dest_lastaccess();
703     dstatbuf.lastmod = other.stat_dest_lastmod();
704     dstatbuf.lastchange = other.stat_dest_lastchange();
705     dstatbuf.mode = other.stat_dest_mode();
706     dstatbuf.userid = other.stat_dest_userid();
707     dstatbuf.groupid = other.stat_dest_groupid();
708     dstatbuf.inode = other.stat_dest_inode();
709     dstatbuf.nlink = other.stat_dest_nlink();
710     dstatbuf.blocks = other.stat_dest_blocks();
711     dstatbuf.rdev = other.stat_dest_rdev();
712     dstatbuf.dev = other.stat_dest_dev();
713 
714     dirsize = 0;
715     select = false;
716     isLink = other.isLink();
717 
718     contentBuf.content = NULL;
719     contentBuf.size = 0;
720 
721     outputBuf = NULL;
722 
723     _ID = -1;
724 
725     m_bookmark_info = NULL;
726 }
727 
728 /*
729  * Method to test for equal fileentry
730  *
731  * Does same extented test to ensure that the fileentry
732  * is a duplicated version
733  */
equals(const FileEntry * fe) const734 bool FileEntry::equals( const FileEntry *fe ) const
735 {
736   if ( fe == NULL ) return false;
737   if ( fe == this ) return true;
738   return equals( *fe );
739 }
740 
equals(const FileEntry & fe) const741 bool FileEntry::equals( const FileEntry &fe ) const
742 {
743   // require name
744   if ( ( fullname == NULL ) || ( fe.fullname == NULL ) ) return false;
745 
746   // require same inode/device
747 
748   //Currently disabled because AVFS can set 0
749   //  if ( statbuf.inode == 0 ) return false;
750   if ( ( statbuf.inode != fe.statbuf.inode ) || ( statbuf.dev != fe.statbuf.dev ) ) return false;
751 
752   // require same size
753   if ( statbuf.size != fe.statbuf.size ) return false;
754 
755   // require same name
756   if ( strcmp( fullname, fe.fullname ) != 0 ) return false;
757 
758   // finally require same times
759 
760   // skip access time check since it might be changed by background file type check
761   // if ( statbuf.lastaccess != fe.statbuf.lastaccess ) return false;
762 
763   if ( statbuf.lastmod != fe.statbuf.lastmod ) return false;
764   if ( statbuf.lastchange != fe.statbuf.lastchange ) return false;
765 
766   return true;
767 }
768 
getID() const769 int FileEntry::getID() const
770 {
771     return _ID;
772 }
773 
setID(int ID)774 void FileEntry::setID( int ID )
775 {
776     _ID = ID;
777 }
778 
setMatchingLabels(const std::list<std::string> & labels)779 void FileEntry::setMatchingLabels( const std::list<std::string> &labels )
780 {
781     if ( labels.empty() == true ) {
782         if ( m_bookmark_info != NULL ) {
783             delete m_bookmark_info;
784             m_bookmark_info = NULL;
785         }
786     } else {
787         if ( m_bookmark_info == NULL ) {
788             m_bookmark_info = new FEBookmarkInfo;
789         }
790         if ( m_bookmark_info->m_matching_labels != NULL ) delete m_bookmark_info->m_matching_labels;
791         m_bookmark_info->m_matching_labels = new std::list<std::string>( labels );
792     }
793 }
794 
getMatchingLabels() const795 const std::list<std::string> &FileEntry::getMatchingLabels() const
796 {
797     if ( m_bookmark_info == NULL ) throw( 1 );
798     if ( m_bookmark_info->m_matching_labels == NULL ) throw( 1 );
799 
800     return *m_bookmark_info->m_matching_labels;
801 }
802 
clearMatchingLabels()803 void FileEntry::clearMatchingLabels()
804 {
805     if ( m_bookmark_info != NULL ) {
806         delete m_bookmark_info;
807         m_bookmark_info = NULL;
808     }
809 }
810 
hasMatchingLabels() const811 bool FileEntry::hasMatchingLabels() const
812 {
813     if ( m_bookmark_info == NULL ) return false;
814     if ( m_bookmark_info->m_matching_labels == NULL ) return false;
815     if ( m_bookmark_info->m_matching_labels->empty() == true ) return false;
816 
817     return true;
818 }
819 
getBookmarkMatch() const820 FileEntry::bookmark_match_t FileEntry::getBookmarkMatch() const
821 {
822     if ( m_bookmark_info == NULL ) return FileEntry::NOT_IN_BOOKMARKS;
823     return m_bookmark_info->m_bookmark_match;
824 }
825 
setBookmarkMatch(bookmark_match_t m)826 void FileEntry::setBookmarkMatch( bookmark_match_t m )
827 {
828     if ( m == NOT_IN_BOOKMARKS ) {
829         if ( m_bookmark_info != NULL ) {
830             m_bookmark_info->m_bookmark_match = m;
831         }
832     } else {
833         if ( m_bookmark_info == NULL ) {
834             m_bookmark_info = new FEBookmarkInfo;
835         }
836         m_bookmark_info->m_bookmark_match = m;
837     }
838 }
839 
setFiletypeFileOutput(const std::string & output)840 void FileEntry::setFiletypeFileOutput( const std::string &output )
841 {
842     m_filetype_file_output = output;
843 }
844 
getFiletypeFileOutput() const845 std::string FileEntry::getFiletypeFileOutput() const
846 {
847     return m_filetype_file_output;
848 }
849 
setMimeType(const std::string & mimetype)850 void FileEntry::setMimeType( const std::string &mimetype )
851 {
852     m_mime_type = mimetype;
853 }
854 
getMimeType() const855 std::string FileEntry::getMimeType() const
856 {
857     return m_mime_type;
858 }
859