File: Fileinfo.cc

package info (click to toggle)
rdfind 1.3.4-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 516 kB
  • ctags: 227
  • sloc: cpp: 1,671; sh: 1,080; makefile: 10
file content (322 lines) | stat: -rw-r--r-- 8,107 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
/*
a class to hold information about a file.

cvs info:
$Revision: 822 $
$Id: Fileinfo.cc 822 2013-06-03 09:25:13Z paul $
Author Paul Sundvall 2006
See LICENSE for details.
*/
#include "config.h"
#include "Fileinfo.hh"

#include <fstream>//for file reading
#include <iostream>//for cout etc
#include <sys/stat.h>//for file info
#include <errno.h>//for errno
#include <unistd.h>//for unlink etc.

#include "Checksum.hh" //checksum calculation



using std::cerr;
using std::endl;

int Fileinfo::fillwithbytes(enum readtobuffermode filltype, 
			    enum readtobuffermode lasttype)
{

  //Decide if we are going to read from file or not.
  //If file is short, first bytes might be ALL bytes!
  if(lasttype!=-1) {
    if(this->size()<= (Fileinfo::filesizetype)m_nbytes) {
      //pointless to read - all bytes in the file are in the field
      //m_somebytes, or checksum is calculated!
      //      cout<<"Skipped reading from file because lasttype="<<lasttype
      //	  <<" and size="<<size()<<endl;
      return 0;
    }
  }

  //set memory to zero 
  //(this command is equivalent to memset(m_somebytes,0,sizeeof(m_somebytes))
  //but this is easier to understand.)
  memset(m_somebytes,0,m_nbytes*sizeof(m_somebytes[0]));
  
  std::fstream f1;
  f1.open(m_filename.c_str(),std::ios_base::in);
  if(!f1.is_open()){
    std::cerr<<"fillwithbytes.cc: Could not open file \""<<m_filename<<"\""<<std::endl;
    return -1;
  }

  
  int checksumtype=Checksum::NOTSET;
  //read some bytes
  switch(filltype) {
  case READ_FIRST_BYTES:
    //read at start of file
    f1.read(m_somebytes,m_nbytes);
    break;
  case READ_LAST_BYTES:
    //read at end of file
    f1.seekg(-m_nbytes,std::ios_base::end);
    f1.read(m_somebytes,m_nbytes);
    break;
  case CREATE_MD5_CHECKSUM://note: fall through is on purpose
    checksumtype=Checksum::MD5;
  case CREATE_SHA1_CHECKSUM:
     checksumtype=Checksum::SHA1;
    {//checksum calculation      
      Checksum chk;
      if(chk.init(checksumtype))
	std::cerr<<"error in checksum init"<<std::endl;
      char buffer[1024];
      int len=1;
      while(len){
	f1.read(buffer,1024);
	len=f1.gcount();
	if(len)
	   if(chk.update((unsigned int)len,(unsigned char*)buffer))
	      	  std::cerr<<"error in update"<<std::endl;
      }

      //store the result of the checksum calculation in somebytes
      int digestlength=chk.getDigestLength();
      if (digestlength<=0 || digestlength>=m_nbytes) 
	std::cerr<<"wrong answer from getDigestLength! FIXME"<<std::endl;
      if(chk.printToBuffer(m_somebytes))
	std::cerr<<"failed writing digest to buffer!!"<<std::endl;
    }
    break;
  default:
    std::cerr<<"does not know how to do that filltype:"<<filltype<<std::endl;
  }
  
  f1.close();
  return 0;
}


bool Fileinfo::readfileinfo(){
  struct stat info;
  m_info.is_file=false;
  m_info.is_directory=false;

  int res;
  do {
    res=stat(m_filename.c_str(), &info);
  } while(res<0 && errno==EINTR);
  
  if (res<0){
    m_info.stat_size=0;
    m_info.stat_ino=0;
    m_info.stat_dev=0;
    std::cerr<<"readfileinfo.cc:Something went wrong when reading file info from \""<<
      m_filename<<"\" :"<<strerror(errno)<<std::endl;
    return false;	    
  }

  //only keep the relevant information
  m_info.stat_size=(Fileinfo::filesizetype) info.st_size;
  m_info.stat_ino= info.st_ino;
  m_info.stat_dev= info.st_dev;

  m_info.is_file=S_ISREG(info.st_mode)?true:false;
  m_info.is_directory=S_ISDIR(info.st_mode)?true:false;
  return true; 
}



const std::string Fileinfo::getduptypestring(const Fileinfo &A) {

  switch (A.getduptype()) {
  case DUPTYPE_UNKNOWN:
    return "DUPTYPE_UNKNOWN";
  case DUPTYPE_FIRST_OCCURRENCE:
    return "DUPTYPE_FIRST_OCCURRENCE";
  case DUPTYPE_WITHIN_SAME_TREE:
    return "DUPTYPE_WITHIN_SAME_TREE";
  case DUPTYPE_OUTSIDE_TREE:
    return "DUPTYPE_OUTSIDE_TREE";
  default:
    std::cerr<<"error. does not know that one"<<std::endl;
  }
  return "error-error";
}

//constructor
Fileinfo::Fileinfostat::Fileinfostat() {
  stat_size=99999;
  stat_ino =99999;
  stat_dev =99999;
  is_file    =false;
  is_directory=false;
}

int Fileinfo::deletefile()
{
  return unlink(name().c_str());
}


int simplifyPath(std::string &path){
  //replace a/./b to a/b
  std::string::size_type pos=std::string::npos;
  do {
    pos=path.find("/./");
    if(pos!=std::string::npos) {
      path.replace(pos,3,"/");
    }
  } while(pos!=std::string::npos);
  //we should get rid of /../ also, but that is more difficult.
  //future work...
  return 0;
}

//prepares target, so that location can point to target in 
//the best way possible
int makeReadyForLink(std::string &target, const std::string &location_)
{
  std::string location(location_);

  //simplify target and location
  simplifyPath(location);
  simplifyPath(target);

  //if target is not absolute, let us make it absolute
  if(target.length()>0 && target.at(0)=='/') {
    //absolute. do nothing.
    //    std::cout<<"absolute"<<std::endl;
  } else {
    //not absolute. make it absolute.
    //    std::cout<<"not absolute"<<std::endl;

    //yes, this is possible to do with dynamically allocated memory, 
    //but it is not portable then (and more work).
    const size_t buflength=256;
    char buf[buflength];
    if(buf!=getcwd(buf,buflength)) {
      std::cerr<<"failed to get current working directory"<<std::endl;
      return -1;
    }
    target=std::string(buf)+std::string("/")+target;
    //    std::cout<<"target is now "<<target<<std::endl;
  }
  return 0;
}

//makes a symlink that points to A
int Fileinfo::makesymlink(const Fileinfo &A) {
  int retval=0;
  //step 1: remove the file
  retval=unlink(name().c_str());
  if(retval) {
    cerr<<"failed to unlink file "<<name()<<endl;
    return retval;
  }

  //step 2: make a symlink.
  //the tricky thing is that the path must be correct, as seen from 
  //the directory where *this is.

  //simplifiy A and *this, so that asdf/../asdfdf are removed

  std::string target=A.name();
  makeReadyForLink(target,name());

  //  std::cout<<"will call symlink("<<target<<","<<name()<<")"<<std::endl;
  retval=symlink(target.c_str(),name().c_str());
  if(retval) {
    cerr<<"failed to make symlink "<<name()<<" to "<<A.name()<<endl;
    return retval;
  }

  return retval;
}

//makes a hard link that points to A
int Fileinfo::makehardlink(const Fileinfo &A) {
  int retval=0;
  //step 1: remove the file
  retval=unlink(name().c_str());
  if(retval) {
    cerr<<"failed to unlink file "<<name()<<endl;
    return retval;
  }
  
  //step 2: make a hardlink.
  retval=link(A.name().c_str(),name().c_str());
  if(retval) {
    cerr<<"failed to make hardlink "<<name()<<" to "<<A.name()<<endl;
    return retval;
  }

  return retval;
}

int Fileinfo::static_deletefile(Fileinfo &A, const Fileinfo &B) {
  //delete A.

  //  cout<<"wants to delete file "<<A.name()<<endl;
  //  return 0;

  return A.deletefile();
}

int Fileinfo::static_makesymlink(Fileinfo &A, const Fileinfo &B) { 
  //  cout<<"wants to make symlink from file "<<A.name()<<" to "<<B.name()<<endl;
  //  return 0;
  return A.makesymlink(B);
}

int Fileinfo::static_makehardlink(Fileinfo &A, const Fileinfo &B) { 
  //  cout<<"wants to make hardlink from file "<<A.name()<<" to "<<B.name()<<endl;
  //  return 0;
  return A.makehardlink(B);
}



bool Fileinfo::compareonbytes(const Fileinfo &a, const Fileinfo &b)
{
  int retval=memcmp(a.getbyteptr(),b.getbyteptr(),m_nbytes);
  return (retval<0);
  /*
  for(int i=0;i<m_nbytes;i++)
    if(a.getreadbyte(i)<b.getreadbyte(i))
      return true;
  return false;
  */
}

bool Fileinfo::equalbytes(const Fileinfo &a, const Fileinfo &b)
{
  int retval=memcmp(a.getbyteptr(),b.getbyteptr(),m_nbytes);
  return (retval==0);
}





bool Fileinfo::compareonsizeandfirstbytes(const Fileinfo &a, const Fileinfo &b)
{
  if (a.size()>b.size())
    return true;
  if (a.size()<b.size())
    return false;
  //must be equal. compare on bytes.
  return compareonbytes(a,b);
}


bool Fileinfo::equalsize(const Fileinfo &a, const Fileinfo &b)
{
  if (a.size()==b.size())
    return true;
  else
    return false;
}