src/get_it_i_say.c

Go to the documentation of this file.
00001 /*
00002 * /giis/get_it_i_say.c-Here we try to recover deleted files
00003 *
00004 * Copyright (C) 2007. G.Lakshmipathi.<lakshmipathi_g@rediffmail.com>
00005 *
00006 */
00007 
00008 
00009 #include "giis.h"
00010 
00011 /*
00012 * get_it() This is will scan through the file entries with the help of verfiy_inode()
00013 * Mofication for giis2:
00014 * Keep track of s_offy and d_offy.
00015 */
00016 
00017 int get_it ()
00018 {
00019   int i, fd, no = 0;
00020   static int search_uid;
00021   search_uid = 0;
00022 //Added for giis4.0
00023   char extension[10];
00024   int glength = 0, ulength = 0, pos, count, typefound;
00025 
00026   if (use_uid == 2)
00027   {
00028     i = force_giis ();
00029     CHECK return 1;
00030   }
00031 
00032   if (use_uid == 1)
00033   {
00034     printf ("\n Enter the User Name....");
00035     scanf ("%s", user);
00036     pwfile = getpwnam (user);
00037     if (pwfile == NULL)
00038     {
00039       printf ("\nPlease Enter Correct user name ");
00040       return 1;
00041     }
00042     use_uid = pwfile->pw_uid;
00043     printf ("\nSearching For %s files with uid=%d", pwfile->pw_name, use_uid);
00044     search_uid = 1;             /* Search for specific users */
00045   }
00046   /* Get by File format */
00047   if (use_uid == 3)
00048   {
00049     printf ("\n Enter any file type:(txt,doc,mp3,c,cpp,dat--etc) :");
00050     scanf ("%s", extension);
00051     search_format = 1;
00052   }
00053 
00054   /* Reset offset of two files */
00055 
00056   d_offy = 0;
00057   s_offy = 0;
00058 
00059 
00060   fd = open (FILE_INFO_FILE, 2);
00061   if (fd == -1)
00062   {
00063     perror ("open");
00064     return -1;
00065   }
00066 
00067   i = read (fd, giis_f.buffer, GIIS_FSIZE);
00068   CHECK while (i > 0)
00069   {
00070     /* Search for given file formats only */
00071     if (search_format == 1)
00072     {
00073       glength = 0;
00074       ulength = 0;
00075       glength = strlen (giis_f.info.name);
00076       ulength = strlen (extension);
00077       ulength++;                //get dot part too .txt /.cpp
00078       pos = glength - ulength;
00079       if (giis_f.info.name[pos] == '.')
00080       {
00081         pos++;
00082         count = 0;
00083         typefound = 1;
00084         for (; pos < glength; pos++, count++)
00085         {
00086           if (giis_f.info.name[pos] != extension[count])
00087           {
00088             typefound = 0;
00089             pos = glength;
00090           }
00091         }
00092         if (typefound)
00093         {
00094 
00095           i = verify_inode (giis_f.info.inode_number);
00096         CHECK}
00097         else
00098           i = 0;
00099       }
00100     }
00101 
00102     /* Specific user is set and this is his entry then verfify else skip.
00103        If use_uid not set search for all files ignore uid */
00104     if (search_uid)
00105     {
00106 
00107       if (giis_f.info.owner == use_uid)
00108       {
00109         i = verify_inode (giis_f.info.inode_number);
00110       CHECK}
00111       else
00112         i = 0;
00113     }
00114     if ((search_format != 1) && (!search_uid))
00115     {
00116       i = verify_inode (giis_f.info.inode_number);
00117     CHECK}
00118     /* Update s_offy and d_offy here */
00119 
00120     if (giis_f.info.is_offset)
00121       s_offy += giis_f.info.is_offset;
00122 
00123 
00124     if (giis_f.info.id_offset)
00125       d_offy += giis_f.info.id_offset;
00126 
00127 
00128     if (i == 1)
00129     {
00130 
00131       get_it_i_say ();
00132 
00133       /* Finally update this entry in file_info_file() */
00134 
00135       giis_f.info.search_flag = 1;      /* Recovered or failed */
00136       lseek (fd, -GIIS_FSIZE, 1);
00137       i = write (fd, giis_f.buffer, GIIS_FSIZE);
00138       if (i != GIIS_FSIZE)
00139       {
00140         perror ("write");
00141         return -1;
00142       }
00143       no = 1;
00144     }
00145     i = read (fd, giis_f.buffer, GIIS_FSIZE);
00146   CHECK}
00147   if (no == 1)
00148   {
00149     printf ("\n\n giis process Completed...");
00150     printf ("\n\t Recovered files   : /giis/got_it");
00151     printf ("\n\t Unrecovered files : /giis/unrecovered");
00152   }
00153   else
00154     printf ("\n\n\t\tNothing Recovered...");
00155   close (fd);
00156   return 1;
00157 }
00158 
00159 /*
00160 * verify_inode() -  This is a helper file to get_it_i_say() this one verifies inode
00161 * is deleted or is being in use.
00162 */
00163 
00164 int verify_inode (unsigned long inode)
00165 {
00166   int i;
00167   fs.inode_number = inode;
00168 
00169   i = find_inode_offset ();
00170   CHECK i = read_inode ();
00171   CHECK if (iin.in.i_links_count == 0)
00172   {
00173     deleted_inode_offset = fs.inode_offset;
00174     return 1;
00175   }
00176   else
00177     return 0;
00178 
00179 }
00180 
00181 /*
00182 * get_it_i_say()-This will try to retrieve the deleted file.
00183 * Mofication for giis2:
00184 * New Access methods for the following flags,
00185 * sfragment_flag=0 files not uses single indirect at all.
00186 * sfragment_flag=1 file uses single indirect but it's already in sequence.
00187 * sfragment_flag=2 file uses single indirect with SIND FILE .
00188 *
00189 * dfragment_flag=0 files not uses double indirect at all.
00190 * dfragment_flag=1 file uses double indirect but it's already in sequence.
00191 * dfragment_flag=2 file uses double indirect with DIND FILE .
00192 *
00193 */
00194 
00195 int get_it_i_say ()
00196 {
00197   int i, fp, fdes, fd, num, hole, eof, count, tfp;
00198   unsigned long indirect_block, iblock[1024];
00199   char name[75] = "/giis/got_it/";
00200   char over[75] = "/giis/unrecovered/";
00201 
00202 
00203   /* just always create a  new file */
00204   strcat (name, giis_f.info.name);
00205 
00206   fp = open (name, 0);
00207   if (fp != -1)
00208   {
00209     /*Already retrieved */
00210     close (fp);
00211     return 1;
00212   }
00213 
00214 
00215   fp = open (name, O_CREAT | O_RDWR | O_TRUNC);
00216   if (fp == -1)
00217   {
00218     printf ("\nFile Not found %s", name);
00219     close (fp);
00220     return -1;
00221   }
00222 
00223 
00224   fd = open (device_name, 0);
00225   if (fd == -1)
00226     ERROR eof = 1;
00227   fileoverwritten = 0;
00228   size = giis_f.info.file_size; /*  Decrement afer every read to denote EOF  */
00229   err_size = 0;                 /* Increment after read for Error check */
00230   gd = 0;                       /* used in get_data_from_block */
00231   for (i = 0; (i <= 14) && eof; i++)
00232   {
00233 
00234 
00235     /*Don't use fragment_flag Here */
00236 
00237     if (i < 12 && giis_f.info.data_block[i] != 0)
00238     {                           /* Direct blocks */
00239       eof = get_data_from_block (fp, fd, giis_f.info.data_block[i]);
00240       /* If Data Overwritten then Quit */
00241       if (fileoverwritten == 444)
00242       {
00243         close (fp);
00244         i = unlink (name);
00245         strcat (over, giis_f.info.name);
00246         tfp = open (over, O_CREAT | O_RDWR | O_TRUNC);
00247         if (tfp == -1)
00248         {
00249           printf ("\nFile Not found %s", over);
00250           return -1;
00251         }
00252         close (tfp);
00253         close (fd);
00254         return 1;
00255       }
00256       if (eof == 0)
00257       {
00258         close (fp);
00259         close (fd);
00260         return 1;
00261       }
00262 
00263       continue;
00264     }
00265 
00266 
00267     /* part 1: Access single indirect blocks  */
00268 
00269     if (i == 12 && giis_f.info.data_block[12] != 0)
00270     {
00271 
00272       indirect_block = giis_f.info.data_block[12];
00273 
00274       /* sfragment_flag=1 just read by incrementing number */
00275 
00276 
00277       if (giis_f.info.sfragment_flag == 1)
00278       {
00279 
00280         for (count = 0; count < 1024; count++)
00281         {                       /* Sequence */
00282           indirect_block++;
00283           eof = get_data_from_block (fp, fd, indirect_block);
00284 
00285 
00286           if (eof == 0)
00287           {
00288             close (fp);
00289             close (fd);
00290             return 1;
00291           }
00292         }
00293       }
00294 
00295       /* sfragment_flag=2 read from sind_info_file */
00296 
00297 
00298 
00299       if (giis_f.info.sfragment_flag == 2)
00300       {                         /* holes here n there */
00301         num = 0;
00302 
00303         fdes = open (SIND_INFO_FILE, 0);
00304         if (fdes == -1)
00305         {
00306           perror ("open");
00307           printf ("\nError No : %d", errno);
00308         }
00309 
00310         lseek (fdes, (s_offy - giis_f.info.is_offset) * sizeof (unsigned long), 0);
00311         read (fdes, iblock, giis_f.info.is_offset * sizeof (unsigned long));
00312         CHECK hole = iblock[num];
00313 
00314         for (count = 0; count < 1024; count++)
00315         {
00316 
00317           if (indirect_block == hole)
00318           {
00319             indirect_block = iblock[num + 1];
00320             num += 2;
00321             hole = iblock[num];
00322           }
00323           else
00324             indirect_block++;
00325 
00326           eof = get_data_from_block (fp, fd, indirect_block);
00327           if (eof == 0)
00328           {
00329             close (fp);
00330             close (fd);
00331             return 1;
00332           }
00333         }
00334       }
00335       continue;
00336     }
00337 
00338     /* part 2: Access double indirect blocks */
00339 
00340     if (i == 13 && giis_f.info.data_block[13] != 0)
00341     {
00342 
00343 
00344       indirect_block = giis_f.info.data_block[13];
00345       indirect_block++;
00346 
00347       /* dfragment_flag=1 just read by incrementing number */
00348 
00349       if (giis_f.info.dfragment_flag == 1)
00350       {
00351         while (eof)
00352         {                       /* Sequence */
00353           indirect_block++;
00354           eof = get_data_from_block (fp, fd, indirect_block);
00355           if (eof == 0)
00356           {
00357             close (fp);
00358             close (fd);
00359             return 1;
00360           }
00361         }
00362 
00363       }
00364 
00365       /* dfragment_flag=2 read from file_info_file */
00366 
00367       if (giis_f.info.dfragment_flag == 2)
00368       {                         /* holes here n there */
00369         num = 0;
00370         fdes = open (DIND_INFO_FILE, 0);
00371         if (fdes == -1)
00372         {
00373           perror ("open");
00374           printf ("\nError No : %d", errno);
00375         }
00376 
00377         lseek (fdes, (d_offy - giis_f.info.id_offset) * sizeof (unsigned long), 0);
00378         read (fdes, iblock, giis_f.info.id_offset * sizeof (unsigned long));
00379         CHECK hole = iblock[num];
00380         count = 0;
00381         /* 4 holes occur first say at [13] itself */
00382         if (hole == (indirect_block - 1))
00383           indirect_block = hole;
00384 
00385         /*
00386            For files more than 8.04 MB we need count to keep trace of 
00387            when to double jump from position 1022 to next.
00388            It's has taken few hours for me to find solution why the above                         if block doesn't reset count.The answer is, 
00389            In situations like we have a hole at indirect_block+1 and count=1023
00390            doesn't enter above block then count goes to beyond 1024 so in the 
00391            following iterations too we can't reset count so we have...
00392          */
00393 
00394         while (eof)
00395         {
00396           if (indirect_block == hole)
00397           {
00398             indirect_block = iblock[num + 1];
00399             num += 2;
00400             hole = iblock[num];
00401             if (count == 1024)
00402               count = 0;
00403           }
00404           else
00405             indirect_block++;
00406 
00407           if (count == 1024)
00408           {
00409             indirect_block++;
00410             count = 0;
00411           }
00412 
00413 
00414           eof = get_data_from_block (fp, fd, indirect_block);
00415           if (eof == 0)
00416           {
00417             close (fp);
00418             close (fd);
00419             return 1;
00420           }
00421           count++;
00422 
00423 
00424         }
00425       }
00426     }
00427 
00428 
00429   }
00430   close (fd);
00431   close (fp);
00432   return 1;
00433 }
00434 
00435 /*
00436 * get_data_from_block() is a helper function to above procedure it computes the content 
00437 * offset of given block number and access that data.
00438 * Modification for giis2:
00439 * Check introduced with help of last_data_block.
00440 */
00441 
00442 int get_data_from_block (int fp, int fd, unsigned long data_block)
00443 {
00444   int i;
00445   unsigned long device_block_number;
00446 /*
00447 static int lg;
00448 char *disp1="\ngiis.........Smile or Sad face?";
00449 char *disp2="                 ";
00450 char disp3[]="|\\-/|\\-/"; 
00451 char disp4[]="               :-";
00452 char disp5[]=")(";
00453 */
00454 
00455 
00456 
00457   /* just for fun */
00458 
00459   /* Some graphics output commented because it's affects speedy recovery 
00460      Removing following comments is not a risky opertions at all. */
00461 
00462 /*              system("clear");
00463                 write(0,disp1,strlen(disp1));
00464                 write(0,disp2,strlen(disp2));
00465                 write(0,&disp3[lg],1);
00466                 write(0,disp4,strlen(disp4));
00467                 write(0,&disp5[lg%2],1);
00468                 lg++;
00469                 if(lg==strlen(disp3))
00470                 lg=0;
00471 */
00472 
00473   fs.block_number = data_block; /* blocks */
00474 
00475   if (fs.block_number != 0)
00476   {
00477 
00478     /* 
00479        First thought some big file are unable to recover since they might be using
00480        fragment blocks.So i let go.Just in final hours i found something you can
00481        call its as a bug  but for me it's big breakthough.
00482 
00483        Here we just can't go and get blocks sometimes blocks might be scattered around
00484        the disk.So make sure that you access  data from all groups.
00485        So Always keep a close eye on block number and it's Group Descriptor
00486 
00487      */
00488 
00489     if (gd == 0)
00490       i = eye_on_gd ();
00491     if (i == -1)
00492     {
00493       printf ("\n\tAbnormal : Group Descriptor not found ");
00494       return 0;
00495     }
00496 
00497     /* Calling eye_on_gd() affect performance so call when it's needed absoultely */
00498 
00499     if (fs.block_number > (fs.block_bitmap + fs.blocks_per_group) ||
00500         fs.block_number < (fs.block_bitmap))
00501       i = eye_on_gd ();
00502     if (i == -1)
00503     {
00504       printf ("\n\tAbnormal : Group Descriptor not found %lu", fs.block_number);
00505       return 0;
00506     }
00507 
00508     device_block_number =
00509       ((fs.block_number - 1) % fs.blocks_per_group) +
00510       fs.group_number * fs.blocks_per_group;
00511     device_block_number += fs.first_data_block;
00512     fs.content_offset =
00513       (unsigned long long) device_block_number *(unsigned long long) fs.block_size;
00514     fs.content_offset += fs.block_size;
00515     //set devicefile to appropriate address
00516     lseek64 (fd, fs.content_offset, 0);
00517 
00518     read_show_file (fd, fp);
00519 
00520     if (fileoverwritten == 444)
00521     {                           //Check for fileoverwritten ???
00522       return 0;
00523     }
00524 
00525     if (size == 0 || fs.block_number == giis_f.info.last_data_block)
00526     {
00527 
00528 
00529       if ((size == 0) && (fs.block_number == giis_f.info.last_data_block)
00530           && (err_size == giis_f.info.file_size))
00531       {
00532         return 0;               /* fine */
00533       }
00534 
00535       else
00536       {
00537         printf ("\n\n\tWarning : %s size differs\n\t", giis_f.info.name);
00538         printf ("Actual Size(Approx):%d MB", ((giis_f.info.file_size / 1024) / 1024));
00539         printf ("\n\tRecovered Only(Approx):%d MB ", ((err_size / 1024) / 1024));
00540         return 0;
00541       }
00542     }
00543     return 444;                 /*... nothing special. my lucky number */
00544 
00545   }
00546 
00547 
00548 }
00549 
00550 
00551 
00552 /*
00553 * force_giis : Tries to recover the requested file. 
00554 * giis4.1:
00555 * concept of version is implemented.
00556 */
00557 
00558 
00559 int force_giis ()
00560 {
00561   int fp, i, exists;
00562   repeat = 0;                   /* If exists == repeat latest version of a file */
00563 
00564   printf ("\n ->Get Lastest Version or First Version of Deleted File ??");
00565   printf ("\n\tPress 0: Get Lastest Version \n\tPress 1: First Version ");
00566   printf ("\n\t Enter your choice :");
00567   scanf ("%d", &get_version);
00568   if (get_version != 0 && get_version != 1)
00569   {
00570     get_version = 0;            //default version is latest .
00571   }
00572 
00573   printf ("\nForcing giis-Warning:Recovered file may be a corrupted one.");
00574   printf ("\nWitch/Which File ?");
00575   scanf ("%s", search_file);
00576 
00577   fp = open (FILE_INFO_FILE, 0);
00578   if (fp == -1)
00579   {
00580     perror ("open");
00581     return -1;
00582   }
00583 
00584   i = read (fp, giis_f.buffer, GIIS_FSIZE);
00585   s_offy = d_offy = 0;
00586 
00587   while (i > 0)
00588   {
00589 
00590     /* update s_offy & d_offy */
00591 
00592     if (giis_f.info.is_offset)
00593       s_offy += giis_f.info.is_offset;
00594 
00595     if (giis_f.info.id_offset)
00596       d_offy += giis_f.info.id_offset;
00597 
00598 
00599     if (strcmp (search_file, giis_f.info.name) == 0)
00600     {
00601       /* Check how many entries are available in giis system file */
00602       exists = file_repeated (giis_f.info.name);
00603 
00604       repeat++;                 /* We created version. 'repeat' of this file */
00605       /* Get Lastest Version */
00606       if (get_version == 0)
00607       {
00608         if (repeat == exists)
00609         {
00610           /* Fetch the last updated version of deleted file */
00611           get_it_i_say ();      /*Never mind about others go and get */
00612           close (fp);
00613           printf ("\n\n\tRecovered       :/giis/got_it");
00614           printf ("\n\tUnrecovered Files :/giis/unrecovered");
00615           return 1;
00616         }
00617       }
00618       if (get_version == 1)
00619       {                         /*Get First version */
00620         get_it_i_say ();        /*Never mind about others go and get */
00621         close (fp);
00622         printf ("\n\n\tRecovered       :/giis/got_it");
00623         printf ("\n\tUnrecovered Files :/giis/unrecovered");
00624         return 1;
00625       }
00626 
00627     }
00628 
00629     i = read (fp, giis_f.buffer, GIIS_FSIZE);
00630   CHECK}
00631   printf ("\n\t%s File not found", search_file);
00632   close (fp);
00633   return 1;
00634 }

Generated on Wed Jul 25 20:43:33 2007 for giis by  doxygen 1.5.1