Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

tarfs_tar.c

Go to the documentation of this file.
00001 
00011 /* ************************************************************************* *
00012  *                                                                           *
00013  *   This program is free software; you can redistribute it and/or modify    *
00014  *   it under the terms of the GNU General Public License as published by    *
00015  *   the Free Software Foundation; either version 2 of the License, or       *
00016  *   (at your option) any later version.                                     *
00017  *                                                                           *
00018  * ************************************************************************* */
00019 
00020 #include "tarfs_tar.h"
00021 #include "tarfs_util.h"
00022 #include "tarfs_common.h"
00023 #include <linux/slab.h>
00024 
00028 typedef struct posix_header
00029 {                    /* byte offset */
00030   char name[100];    /*   0 */
00031   char mode[8];      /* 100 */
00032   char uid[8];       /* 108 */
00033   char gid[8];       /* 116 */
00034   char size[12];     /* 124 */
00035   char mtime[12];    /* 136 */
00036   char chksum[8];    /* 148 */
00037   char typeflag;     /* 156 */
00038   char linkname[100];/* 157 */
00039   char magic[6];     /* 257 */
00040   char version[2];   /* 263 */
00041   char uname[32];    /* 265 */
00042   char gname[32];    /* 297 */
00043   char devmajor[8];  /* 329 */
00044   char devminor[8];  /* 337 */
00045   char prefix[155];  /* 345 */
00046   char pad [12];     /* 500 */
00047 } posix_header;
00048 
00049 #define TMAGIC   "ustar"
00050 #define TMAGLEN  6
00051 #define TVERSION "00"   
00052 #define TVERSLEN 2
00053 
00054 /* Values used in typeflag field.  */
00055 #define REGTYPE  '0'    
00056 #define AREGTYPE '\0'           
00057 #define LNKTYPE  '1'            
00058 #define SYMTYPE  '2'            
00059 #define CHRTYPE  '3'            
00060 #define BLKTYPE  '4'            
00061 #define DIRTYPE  '5'            
00062 #define FIFOTYPE '6'            
00063 #define CONTTYPE '7'            
00065 /* Bits used in the mode field, values in octal.  */
00066 #define TSUID    04000          
00067 #define TSGID    02000          
00068 #define TSVTX    01000          
00069 /* file permissions */
00070 #define TUREAD   00400          
00071 #define TUWRITE  00200          
00072 #define TUEXEC   00100          
00073 #define TGREAD   00040          
00074 #define TGWRITE  00020          
00075 #define TGEXEC   00010          
00076 #define TOREAD   00004          
00077 #define TOWRITE  00002          
00078 #define TOEXEC   00001    
00086 #define OFFSET_BY_INO(X) ((X) - 1)
00087 
00096 int is_tar(posix_header* blok)
00097 {
00098   int j = 0;
00099   unsigned int checksum = 0;
00100 
00101   //kontrola spravnosti bloku
00102   //zajimave, TMAGIC a TVERSION nak nesouhlasej (asi se ponek zmenil format),
00103   //takze tomu trochu pomuzu
00104   if (memcmp(blok->magic, TMAGIC, TMAGLEN - 1)) {
00105     return 0;
00106   }
00107 
00108   //kontrola kontrolniho souctu - soucet bytu hlavicky az na checksum(ten se bere jako '')
00109   for (j = 0; j < sizeof(posix_header); j++){
00110     checksum += ((unsigned char*)(blok))[j];
00111   }
00112 
00113   checksum += 8 * ' ';
00114 
00115   for (j = 0; j < 8; j++) {
00116     checksum -= ((unsigned char*) blok->chksum)[j];
00117   }
00118 
00119   checksum -= oct_to_dec(blok->chksum, 6);//6 staci  - vic stejne nejde
00120 
00121   //nevychazi kontrolni soucet
00122   if(checksum) {
00123     return 0;
00124   }
00125   return 1;
00126 }
00127 
00128 
00137 int tar_quick_validation(struct super_block* s)
00138 {
00139    posix_header* blok;
00140    int ret_value;
00141 
00142    blok = (posix_header*) kmalloc(sizeof(posix_header), GFP_KERNEL);
00143 
00144    if (blok == 0 || s == 0) {
00145      return 0;
00146    }
00147 
00148    if (!read_block(s, 0, blok)) {
00149      kfree(blok);
00150      return 0;
00151    }
00152 
00153    ret_value = is_tar(blok);
00154 
00155    kfree(blok);
00156 
00157    return ret_value;
00158 }
00159 
00160 
00166 unsigned long get_root_ino_pom(posix_header* blok)
00167 {
00168   if (!blok) {
00169     return TARFS_EVAL;
00170   }
00171   // je tam zabaleny i ./
00172   if(blok->name[0] == '.' && blok->name[1] == '/' && blok->typeflag == DIRTYPE) {
00173     return 1;
00174   }
00175   return TARFS_ROOT_INO;
00176 }
00177 
00184 unsigned long tar_get_root_ino(struct super_block* s)
00185 {
00186   unsigned long ret_val;
00187   unsigned long size;
00188   unsigned long i = 0;
00189   posix_header* blok;
00190 
00191   if(!(blok = (posix_header*) kmalloc(sizeof(posix_header), GFP_KERNEL))) {
00192     return -1;
00193   }
00194 
00195   while (read_block(s, i, blok)) {
00196 
00197     if (!is_tar(blok)) {
00198       //asi jsem na konci taru (nebo je archive poskozenej, nebo to tu neni)
00199       goto EOut1;
00200     }
00201 
00202     switch(blok->typeflag) {
00203       default :
00204         goto EOut1;
00205         break;
00206 
00207       case 'L' :   //dalsi blok bude jmeno souboru, pak bude nasledovat ten soubor
00208       case 'K' :   // dalsi blok bude jmeno linku, pak bude nasledovat ten link
00209         size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00210         i += hcc(size, TARFS_BLKSIZE);
00211         i++;
00212         break;
00213 
00214       case REGTYPE ://normalni soubor - alternativni kod
00215       case AREGTYPE://normalni soubor - preferovany kod
00216       case LNKTYPE ://hardlink
00217       case SYMTYPE ://symlink, vratim info o symlinku
00218       case CHRTYPE :;//znakove zarizeni
00219       case BLKTYPE :;//blokove zarizeni
00220       case DIRTYPE :;//adresar
00221       case FIFOTYPE:
00222         ret_val = get_root_ino_pom(blok);
00223         kfree(blok);
00224         return ret_val;
00225         break;
00226     }
00227   }
00228 
00229   // errors
00230 EOut1:
00231   kfree(blok);
00232   return TARFS_EVAL;
00233 }
00234 
00241 unsigned long tar_length(struct super_block* s)
00242 {
00243   unsigned long i = 0;
00244   unsigned long size = 0;
00245   posix_header *blok;
00246 
00247   //rychlou validaci delam proto, abych objevil, ze dany soubor je
00248   //"prazdny tar", tj. dva nulove bloky
00249   if (!tar_quick_validation(s)) {
00250     goto EOut1;
00251   }
00252 
00253   blok = (posix_header*) kmalloc(sizeof(posix_header), GFP_KERNEL);
00254 
00255   if(!blok) {
00256     goto EOut1;
00257   }
00258 
00259   while (read_block(s, i, blok)) {
00260 
00261     if (!is_tar(blok)) {
00262       //asi jsem na konci taru (to jest, jsou tu 2 nulove bloky)
00263       if (is_nullblock(blok, TARFS_BLKSIZE) && read_block(s, i + 1, blok)) {
00264         if(is_nullblock(blok,TARFS_BLKSIZE)) {
00265           kfree(blok);
00266           //je to tar;
00267           return i + 1;//vracim delku
00268         } else {
00269           //neni to tar
00270           break;
00271         }
00272       }
00273       //neni to tar
00274       break;
00275     }
00276 
00277     size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00278     //preskocim datove bloky
00279     i += hcc(size,TARFS_BLKSIZE);
00280     i++;
00281   }
00282 
00283   kfree(blok);
00284 
00285 EOut1:
00286   //neni to tar
00287   return 0;
00288 }
00289 
00290 
00301 int pom_read_name(struct super_block* s, char** file_name, unsigned long size, unsigned long offset)
00302 {
00303   unsigned long i;
00304   unsigned long block_count;
00305   void* blok;
00306 
00307   if (!(blok = kmalloc(TARFS_BLKSIZE * sizeof(char), GFP_KERNEL))) {
00308     goto EOut3;
00309   }
00310 
00311   if (!(*file_name = (char*) kmalloc((size + 1) * sizeof(char), GFP_KERNEL))) {
00312     goto EOut2;
00313   }
00314 
00315   block_count = hcc(size, TARFS_BLKSIZE);
00316 
00317   if (block_count < 1) {
00318     goto EOut1;
00319   }
00320 
00321   for ( i = 0; i < block_count; i++) {
00322     if (!read_block(s, offset + i, blok)) {
00323       goto EOut1;
00324     }
00325     memcpy((*file_name) + TARFS_BLKSIZE * i, blok, (unsigned int) ((size - TARFS_BLKSIZE * i < TARFS_BLKSIZE) ? size - TARFS_BLKSIZE * i : TARFS_BLKSIZE));
00326   }
00327 
00328   (*file_name)[size] = 0; //ukoncim retezec
00329   kfree(blok);
00330   return 1;
00331 
00332   // errors
00333 EOut1:
00334   kfree(*file_name);
00335 
00336 EOut2:
00337   kfree(blok);
00338 
00339 EOut3:
00340   return 0;
00341 }
00342 
00343 
00352 unsigned long offset_by_name(struct super_block* s, char* name)
00353 {
00354   char* file_name;
00355   unsigned long size;
00356   unsigned long correction = 0;
00357   posix_header* blok;
00358   unsigned long i = 0;
00359   int skip = 0; //skip rika, zda automaticky preskocit dalsi header blok taru
00360 
00361   if (!name || *name == 0) {
00362     return TARFS_EVAL;
00363   }
00364 
00365   /*
00366   if(!strcmp(name,"/")) {
00367     //korenovy adresar dostane 0;
00368     return 0;
00369   } */
00370 
00371   if (! (blok = (posix_header*) kmalloc(sizeof(posix_header), GFP_KERNEL))) {
00372     goto EOut2;
00373   }
00374 
00375   while (read_block(s, i, blok)) {
00376 
00377       if(!is_tar(blok)) {
00378         //asi jsem na konci taru (nebo je archive poskozenej, nebo to tu neni)
00379         goto EOut1;
00380       }
00381 
00382       if (skip) {
00383         size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00384         //preskocim datove bloky
00385         i += hcc(size, TARFS_BLKSIZE);
00386         i++;
00387         skip = 0;
00388         continue;
00389       }
00390 
00391       switch (blok->typeflag) {
00392         default :
00393           //nepodporovany/spatny format
00394           goto EOut1;
00395           break;
00396 
00397         case 'K' :
00398           // dalsi blok bude jmeno linku, pak bude nasledovat ten link
00399           size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00400 
00401           if (size == 0) {
00402             //neni to tar
00403             goto EOut1;
00404           }
00405 
00406           size--;
00407 
00408           //preskocim datove bloky
00409           correction = hcc(size,TARFS_BLKSIZE) + 1;
00410           i += hcc(size, TARFS_BLKSIZE);
00411           break;
00412 
00413         case 'L' :
00414           // dalsi blok bude jmeno souboru, pak bude nasledovat ten soubor
00415           size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00416 
00417           if (size == 0) {
00418             //neni to tar
00419             goto EOut1;
00420           }
00421 
00422           size--;
00423 
00424           if (pom_read_name(s, &file_name, size, i + 1)) {
00425             if (!file_name) {
00426               goto EOut1;
00427             }
00428             if(name_comparator(file_name, name, size)) {
00429               //nasel jsem to:-)
00430               kfree(file_name);
00431               kfree(blok);
00432               return i - correction;
00433             }
00434             if (file_name) {
00435               kfree(file_name);
00436             }
00437             skip = 1;//dalsi bude pomocny header tehoz souboru
00438             //preskocim datove bloky
00439             i += hcc(size, TARFS_BLKSIZE);
00440             correction = 0;
00441             break;
00442           }
00443 
00444         case REGTYPE ://normalni soubor - alternativni kod
00445         case AREGTYPE://normalni soubor - preferovany kod
00446         case LNKTYPE ://hardlink
00447         case SYMTYPE ://symlink, vratim info o symlinku
00448         case CHRTYPE :;//znakove zarizeni
00449         case BLKTYPE :;//blokove zarizeni
00450         case DIRTYPE :;//adresar
00451         case FIFOTYPE:;//pojmenovana pipe
00452 
00453           if (name_comparator(blok, name, 100)) {
00454             //uspech
00455             kfree(blok);
00456             return i - correction;
00457           } else {
00458             size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00459             //preskocim datove bloky
00460             i += hcc(size, TARFS_BLKSIZE);
00461             correction = 0;
00462             break;
00463           }
00464           break;
00465 
00466       }//konec switch
00467       i++;
00468   }
00469 
00470   // errors
00471 EOut1:
00472   kfree(blok);
00473   //tak sem bych se dostat nikdy nemel, jestli jo, tak je vadnej archive
00474 EOut2:
00475   return TARFS_EVAL;
00476 }
00477 
00492 unsigned long offset_by_name2(struct super_block* s, unsigned long pos, char* name, unsigned int fsize)
00493 {
00494   char* file_name;
00495   unsigned long size;
00496   unsigned long correction = 0;
00497   posix_header *blok;
00498   unsigned long i = pos;
00499   int skip = 0; //skip rika, zda automaticky preskocit dalsi header blok taru
00500 
00501   if (!name || *name == 0) {
00502     goto EOut2;
00503   }
00504 
00505   blok = (posix_header*) kmalloc(sizeof(posix_header), GFP_KERNEL);
00506 
00507 
00508   while (read_block(s, i, blok)) {
00509 
00510     if(!is_tar(blok)){
00511       //asi jsem na konci taru (nebo je archive poskozenej, nebo to tu neni)
00512       goto EOut1;
00513     }
00514 
00515     if (skip) {
00516       size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00517       //preskocim datove bloky
00518       i += hcc(size, TARFS_BLKSIZE);
00519       i++;
00520       skip = 0;
00521       continue;
00522     }
00523 
00524     switch(blok->typeflag) {
00525 
00526       default :
00527         //nepodporovany/spatny format
00528         goto EOut1;
00529         break;//break pro soumernost :-)
00530 
00531       case 'K' :
00532         // dalsi blok bude jmeno linku, pak bude nasledovat ten link
00533         size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00534 
00535         if (size == 0) {
00536           goto EOut1;
00537         }
00538 
00539         size--;
00540 
00541         //preskocim datove bloky
00542         correction = hcc(size, TARFS_BLKSIZE) + 1;
00543         i += hcc(size, TARFS_BLKSIZE);
00544         break;
00545 
00546       case 'L' :
00547         // dalsi blok bude jmeno souboru, pak bude nasledovat ten soubor
00548         size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00549 
00550         if (size == 0) {
00551           goto EOut1;
00552         }
00553 
00554         size--;
00555 
00556         if (pom_read_name(s, &file_name, size, i + 1)) {
00557 
00558           if (!file_name) {
00559             goto EOut1;
00560           }
00561 
00562           if (name_comparator2(file_name, name, size, fsize)) {
00563             //nasel jsem to:-)
00564             kfree(file_name);
00565             kfree(blok);
00566             return i - correction;
00567           }
00568 
00569           if (file_name) {
00570             kfree(file_name);
00571           }
00572 
00573           //dalsi bude pomocny header tehoz souboru
00574           skip = 1;
00575 
00576           //preskocim datove bloky
00577           i += hcc(size, TARFS_BLKSIZE);
00578           correction = 0;
00579           break;
00580         }
00581 
00582       case REGTYPE ://normalni soubor - alternativni kod
00583       case AREGTYPE://normalni soubor - preferovany kod
00584       case LNKTYPE ://hardlink
00585       case SYMTYPE ://symlink, vratim info o symlinku
00586       case CHRTYPE :;//znakove zarizeni
00587       case BLKTYPE :;//blokove zarizeni
00588       case DIRTYPE :;//adresar
00589       case FIFOTYPE:;//pojmenovana pipe
00590 
00591         size = short_name_size(blok->name);
00592 
00593         if (name_comparator2(blok->name, name, size, fsize)) {
00594           //uspech
00595           kfree(blok);
00596           return i - correction;
00597         } else {
00598           size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00599           //preskocim datove bloky
00600           i += hcc(size, TARFS_BLKSIZE);
00601           correction = 0;
00602         }
00603         break;
00604 
00605     } //konec switch
00606     i++;
00607   }
00608 
00609   //tak sem bych se dostat nikdy nemel, jestli jo, tak je vadnej archive
00610   // errors
00611 EOut1:
00612   kfree(blok);
00613 
00614 EOut2:
00615   return TARFS_EVAL;
00616 }
00617 
00618 
00631 unsigned long skip_blocks(struct super_block* s, unsigned long whence)
00632 {
00633   unsigned long size;
00634   unsigned long i = whence;
00635 
00636   posix_header* blok;
00637 
00638   if (!(blok = (posix_header*) kmalloc(sizeof(posix_header), GFP_KERNEL))) {
00639     goto EOut2;
00640   }
00641 
00642   while (read_block(s, i, blok)) {
00643     if (!is_tar(blok)){
00644       //jsem na konci taru => archive je  poskozeny
00645       goto EOut1;
00646     }
00647 
00648     switch (blok->typeflag) {
00649 
00650       default :
00651         goto EOut1;
00652         break;
00653 
00654       case 'L' :   //dalsi blok bude jmeno souboru, pak bude nasledovat ten soubor
00655       case 'K' :   // dalsi blok bude jmeno linku, pak bude nasledovat ten link
00656         size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00657         i += hcc(size, TARFS_BLKSIZE) + 1;
00658         break;
00659 
00660       case REGTYPE ://normalni soubor - alternativni kod
00661       case AREGTYPE://normalni soubor - preferovany kod
00662       case LNKTYPE ://hardlink
00663       case SYMTYPE ://symlink, vratim info o symlinku
00664       case CHRTYPE :;//znakove zarizeni
00665       case BLKTYPE :;//blokove zarizeni
00666       case DIRTYPE :;//adresar
00667       case FIFOTYPE:
00668         kfree(blok);
00669         return i;
00670         break;
00671     }
00672   }
00673 
00674   // errors
00675 EOut1:
00676   kfree(blok);
00677 
00678 EOut2:
00679   return TARFS_EVAL;
00680 }
00681 
00682 
00690 int get_type(posix_header* blok, unsigned* type)
00691 {
00692   switch(blok->typeflag) {
00693     default :
00694       //nechci ani 'K' a 'L'
00695       *type = DT_UNKNOWN;
00696       return -1;
00697       break;
00698 
00699     case REGTYPE ://normalni soubor - alternativni kod
00700     case AREGTYPE://normalni soubor - preferovany kod
00701     case LNKTYPE ://hardlink
00702       *type = DT_REG;
00703       break;
00704 
00705     case SYMTYPE ://symlink, vratim info o symlinku
00706       *type = DT_LNK;
00707       break;
00708 
00709     case CHRTYPE ://znakove zarizeni
00710       *type = DT_CHR;
00711       break;
00712 
00713     case BLKTYPE ://blokove zarizeni
00714       *type = DT_BLK;
00715       break;
00716 
00717     case DIRTYPE ://adresar
00718       *type = DT_DIR;
00719       break;
00720 
00721     case FIFOTYPE: //pojmenovana pipe
00722       *type = DT_FIFO;
00723       break;
00724   }
00725   return 0;
00726 }
00727 
00739 int tar_fill_inode(struct super_block* s, struct inode* inode, int* rdev)
00740 {
00741   unsigned long offset;
00742   unsigned long size = 0;
00743   int should_continue = 1;
00744   char* link_name = 0;
00745   int ret_type = 0;
00746   posix_header* blok;
00747 
00748   // root. Na to tu mame jinou funkci, ktera se mela zavolat
00749   if (inode->i_ino == TARFS_ROOT_INO) {
00750     goto EOut3;
00751   }
00752   offset = OFFSET_BY_INO(inode->i_ino);
00753 
00754   blok = (posix_header*) kmalloc(sizeof(posix_header), GFP_KERNEL);
00755   if (!blok) {
00756     goto EOut3;
00757   }
00758 
00759   while (should_continue) {
00760 
00761     if ( !read_block(s, offset, blok) || !is_tar(blok) ) {
00762       goto EOut1;
00763     }
00764 
00765     switch (blok->typeflag) {
00766       case 'L' :
00767         //dalsi blok bude jmeno souboru, pak bude nasledovat ten soubor
00768         offset = skip_blocks(s, offset);
00769         if (offset == TARFS_EVAL) {
00770           goto EOut1;
00771         }
00772         break;
00773 
00774       case 'K' :
00775         // dalsi blok bude jmeno linku, pak bude nasledovat ten link
00776         size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00777         size--;
00778 
00779         if (!pom_read_name(s, &link_name, size, offset + 1)) {
00780           goto EOut2;
00781         }
00782 
00783         offset = skip_blocks(s, offset);
00784         if (offset == TARFS_EVAL) {
00785           goto EOut2;
00786         }
00787         break;
00788 
00789       case REGTYPE :
00790         //normalni soubor - alternativni kod
00791       case AREGTYPE:
00792         //normalni soubor - preferovany kod
00793         //dodej si typ souboru
00794         ret_type = S_IFREG;
00795         should_continue = 0;
00796         break;
00797 
00798       case LNKTYPE :
00799         //jako typ souboru si dej normal file
00800         if (!link_name) {
00801             //jeste jsem to nenacetl
00802             size = short_name_size(blok->linkname);
00803             if(!(link_name = (char*) kmalloc((size + 1) * sizeof(char), GFP_KERNEL))) {
00804               goto EOut2;
00805             }
00806             memcpy(link_name, blok->linkname, (unsigned int) size);
00807             link_name[size] = 0;
00808         }
00809 
00810         offset = offset_by_name(s, link_name);
00811         kfree(link_name);
00812 
00813         if (offset == TARFS_EVAL) {
00814           goto EOut2;
00815         }
00816 
00817         link_name = 0;
00818         size = 0;
00819         break;
00820 
00821       case SYMTYPE :
00822         if(link_name) {
00823           inode->i_size = strlen(link_name);//linkname by mel byt null-terminated
00824           kfree(link_name);
00825         } else {
00826           inode->i_size = short_name_size(blok->linkname);
00827         }
00828         ret_type = S_IFLNK;
00829         should_continue = 0;
00830         break;
00831 
00832       case CHRTYPE :
00833         //znakove zarizeni
00834         ret_type = S_IFCHR;
00835         *rdev = kdev_t_to_nr(MKDEV((int) oct_to_dec(blok->devmajor, 7), (int) oct_to_dec(blok->devminor, 7)));
00836         should_continue = 0;
00837         break;
00838 
00839       case BLKTYPE :
00840         //blokove zarizeni
00841         ret_type = S_IFBLK;
00842         *rdev = kdev_t_to_nr(MKDEV((int) oct_to_dec(blok->devmajor, 7), (int) oct_to_dec(blok->devminor, 7)));
00843         should_continue = 0;
00844         break;
00845 
00846       case FIFOTYPE:
00847         //pojmenovana pipe
00848         //zatim nevim, jak vyplnit
00849         ret_type = S_IFIFO;
00850         should_continue = 0;
00851         break;
00852 
00853       case DIRTYPE :
00854         //adresar
00855         ret_type = S_IFDIR;
00856         should_continue = 0;
00857         break;
00858 
00859       default  :
00860         if(link_name) {
00861           kfree(link_name);
00862         }
00863         kfree(blok);
00864         return 0;
00865         break;
00866     }
00867   }
00868 
00869 
00870   //nacetl jsem typove zavisle udaje, takze nactu jeste to, co je spolecne
00871 
00872   //nactu mtime(nic vic posix_verze taru neobsahuje - mimo to, jsme read only,
00873   //takze na tom tolik nezalezi
00874   inode->i_ctime = (time_t) inode->i_atime = inode->i_mtime = oct_to_dec(blok->mtime, TARFS_NUMLENGTH);
00875 
00876   //nactu size, pouze pokud to neni symlink.. ten ma jinou velikost
00877   if (blok->typeflag != SYMTYPE) {
00878     inode->i_size = (loff_t) oct_to_dec(blok->size, TARFS_NUMLENGTH);
00879   }
00880 
00881   //nactu gid
00882   inode->i_gid = (gid_t) oct_to_dec(blok->gid, 7);
00883   //nactu uid
00884   inode->i_uid = (uid_t) oct_to_dec(blok->uid, 7);
00885   //nactu mode
00886   inode->i_mode = (umode_t) oct_to_dec(blok->mode, 7);
00887 
00888   //jsme read_only, takze to staci (mimo to, zjisteni by trvalo v taru dlouho)
00889   inode->i_nlink = 1;
00890 
00891   kfree(blok);
00892   return ret_type;
00893 
00894   // errors
00895 EOut1:
00896   kfree(blok);
00897 EOut2:
00898   if (link_name != 0) {
00899     kfree(link_name);
00900   }
00901 EOut3:
00902   return 0;
00903 }
00904 
00905 
00915 unsigned long find_nolink(struct super_block* s, unsigned long ino)
00916 {
00917   unsigned long offset;
00918   char* link_name = 0;
00919   unsigned long size = 0;
00920   unsigned int linklen;
00921   posix_header* blok;
00922 
00923   // inode je offset + 1
00924   offset = ino - 1;
00925 
00926   if( !(blok = (posix_header*) kmalloc(sizeof(posix_header), GFP_KERNEL)) ) {
00927     goto EOut2;
00928   }
00929 
00930   while (1) {
00931 
00932     if (!read_block(s, offset, blok) || !is_tar(blok)) {
00933       if (link_name != 0) {
00934         kfree(link_name);
00935       }
00936       goto EOut1;
00937     }
00938 
00939     switch(blok->typeflag) {
00940       case 'L' :
00941         //dalsi blok bude jmeno souboru, pak bude nasledovat ten soubor
00942         offset = skip_blocks(s, offset);
00943         if (offset == TARFS_EVAL) {
00944           goto EOut1;
00945         }
00946         break;
00947 
00948       case 'K' :
00949         // dalsi blok bude jmeno linku, pak bude nasledovat ten link
00950         size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00951         size--;
00952 
00953         if (link_name != 0) {
00954           goto EOut1;
00955         }
00956 
00957         if (!pom_read_name(s, &link_name, size, offset + 1)) {
00958           goto EOut1;
00959         }
00960 
00961         offset = skip_blocks(s, offset);
00962         if (offset == TARFS_EVAL) {
00963           kfree(link_name);
00964           goto EOut1;
00965         }
00966         break;
00967 
00968       case LNKTYPE :
00969         if (!link_name) {
00970           //jeste jsem to nenacetl
00971           linklen = short_name_size(blok->linkname);
00972           if (!(link_name = (char*) kmalloc((linklen + 1) * sizeof(char), GFP_KERNEL))) {
00973             goto EOut1;
00974           }
00975           memcpy(link_name, blok->linkname, linklen);
00976           link_name[linklen] = 0;
00977         }
00978 
00979         offset = offset_by_name(s, link_name);
00980         kfree(link_name);
00981 
00982         if (offset == TARFS_EVAL) {
00983           goto EOut1;
00984         }
00985 
00986         link_name = 0;
00987         break;
00988 
00989       case REGTYPE ://normalni soubor - alternativni kod
00990       case AREGTYPE://normalni soubor - preferovany kod
00991       case SYMTYPE ://symlink, vratim info o symlinku
00992       case CHRTYPE ://znakove zarizeni
00993       case BLKTYPE ://blokove zarizeni
00994       case FIFOTYPE://pojmenovana pipe
00995       case DIRTYPE ://adresar
00996         if(link_name) {
00997           kfree(link_name);
00998           link_name = 0;
00999         }
01000 
01001         kfree(blok);
01002         return offset;
01003         break;
01004 
01005       default:
01006         if (link_name) {
01007           kfree(link_name);
01008         }
01009         goto EOut1;
01010         break;
01011     }
01012   }
01013 
01014   // errors
01015 EOut1:
01016   kfree(blok);
01017 
01018 EOut2:
01019   return TARFS_EVAL;
01020 }
01021 
01022 
01030 char* symlinkname(struct super_block* s, unsigned long ino)
01031 {
01032   unsigned long pos;
01033   unsigned long size;
01034   unsigned int linklen;
01035   char* ret_val;
01036   posix_header* blok;
01037 
01038   if (!(blok = (posix_header*) kmalloc(sizeof(posix_header), GFP_KERNEL))) {
01039     goto EOut2;
01040   }
01041 
01042   pos = OFFSET_BY_INO(ino);
01043 
01044   if (!read_block(s, pos, blok) || !is_tar(blok)) {
01045     goto EOut1;
01046   }
01047 
01048   if (blok->typeflag == 'K') {
01049     size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
01050     size--;
01051 
01052     if (!pom_read_name(s, &ret_val, size, pos + 1)) {
01053       goto EOut1;
01054     }
01055 
01056     pos = skip_blocks(s, pos + hcc(size, TARFS_BLKSIZE) + 1);
01057 
01058     if (!read_block(s, pos, blok) || !is_tar(blok) || blok->typeflag != SYMTYPE) {
01059       kfree(ret_val);
01060       goto EOut1;
01061     }
01062     kfree(blok);
01063     return ret_val;
01064   }
01065 
01066   if (blok->typeflag == SYMTYPE) {
01067     linklen = short_name_size(blok->linkname);
01068 
01069     if( !(ret_val = (char*) kmalloc(linklen * sizeof(char), GFP_KERNEL)) ) {
01070       goto EOut1;
01071     }
01072 
01073     memcpy(ret_val, blok->linkname, linklen);
01074 
01075     kfree(blok);
01076     return ret_val;
01077   }
01078 
01079   // errors
01080 EOut1:
01081   kfree(blok);
01082 
01083 EOut2:
01084   return 0;
01085 }
01086 
01099 unsigned long tar_read_page(struct super_block* s, struct inode* inode, loff_t offset, void* buffer)
01100 {
01101   char* blok;
01102   unsigned long diff;
01103   unsigned long start_shift;
01104   unsigned long end_shift;
01105   unsigned long pos;
01106   unsigned long j;
01107   char* linkname;
01108 
01109   if (offset > inode->i_size) {
01110     goto EOut2;
01111   }
01112 
01113   //korenovy adresar ma nulocou velikost, takze prectu 0 bytu
01114   if (inode->i_ino == TARFS_ROOT_INO) {
01115       return 0;
01116   }
01117 
01118   //do diff dam minimum z PAGE_SIZE a inode->i_size - offset,
01119   //tj. v diff je pocet bytu, ktere prectu
01120   diff = (unsigned long) (inode->i_size - offset);
01121   diff = (unsigned long) ((diff > PAGE_SIZE) ? PAGE_SIZE : diff);
01122 
01123   //kdyz nemam co cist, tak nebudu zbytecne cist ze souboru
01124   if (!diff) {
01125     return 0;
01126   }
01127 
01128   //pokud to neni symlink, nastavi linkname na 0
01129   linkname = symlinkname(s, inode->i_ino);
01130   
01131   if (linkname) {
01132     memcpy(buffer, linkname + offset, (unsigned int) diff);
01133     memset((void*) (buffer + diff), 0, (unsigned int) (PAGE_SIZE - diff));
01134     kfree(linkname);
01135     return 2;
01136   }
01137 
01138   blok = (char*) kmalloc(TARFS_BLKSIZE, GFP_KERNEL);
01139   if (!blok) {
01140     goto EOut2;
01141   }
01142 
01143   pos = find_nolink(s, inode->i_ino);
01144 
01145   if (pos == TARFS_EVAL) {
01146     goto EOut1;
01147   }
01148   pos++; //skocim na data
01149 
01150   start_shift = (unsigned long) (offset / TARFS_BLKSIZE);
01151   end_shift = hcc((unsigned long) offset + diff, TARFS_BLKSIZE);
01152 
01153   //pokud je offset zarovnany - asi nejcastejsi pripad, proto osetreno zvlast
01154   if (offset % TARFS_BLKSIZE == 0) {
01155     //nacte buffer
01156     for (j = start_shift; j < end_shift; j++) {
01157       if (!read_block(s, pos + j, blok)) {
01158         goto EOut1;
01159       }
01160       memcpy(buffer + TARFS_BLKSIZE * (j - start_shift), blok, TARFS_BLKSIZE);
01161     }
01162     //doplnim buffer nulama(abych nenacital nahodna data)
01163     memset((void*) (buffer + diff), 0, (unsigned int) (PAGE_SIZE - diff));
01164     kfree(blok);
01165     return 1;
01166   }
01167   //jinak budu muset nacist o blok vic a uparavit okraje
01168 
01169   //else
01170   //nacte prostredek bufferu
01171   for (j = start_shift + 1; j < end_shift - 1; j++) {
01172     if (!read_block(s, pos + j, blok)) {
01173       goto EOut1;
01174     }
01175     memcpy((void*) (buffer + TARFS_BLKSIZE * (j - start_shift) - offset % TARFS_BLKSIZE), blok, TARFS_BLKSIZE);
01176   }
01177 
01178   //nactu zacatek bufferu
01179   if (!read_block(s, pos + start_shift, blok)) {
01180     goto EOut1;
01181   }
01182   memcpy(buffer, blok + offset % TARFS_BLKSIZE, (unsigned int) (TARFS_BLKSIZE - offset % TARFS_BLKSIZE));
01183 
01184   //nactu konec bufferu
01185   if (!read_block(s, pos + end_shift - 1, blok)) {
01186     goto EOut1;
01187   }
01188   memcpy((void*) (buffer + TARFS_BLKSIZE * (j - start_shift) - offset % TARFS_BLKSIZE), blok, (unsigned int) (offset % TARFS_BLKSIZE));
01189 
01190   //doplnim buffer nulama(abych nenacital nahodna data)
01191   memset((void*) (buffer + diff), 0, (unsigned int) (PAGE_SIZE - diff));
01192 
01193   // vse nacteno OK
01194   kfree(blok);
01195   return 1;
01196 
01197   // errors
01198 EOut1:
01199   kfree(blok);
01200 
01201 EOut2:
01202   return TARFS_EVAL;
01203 }
01204 
01205 
01218 unsigned long tar_readdir(struct file* filp, void* dirent, filldir_t filldir)
01219 {
01220   unsigned long i;
01221   unsigned long pos;
01222   unsigned long dsize;
01223   unsigned long fsize;
01224   char* dir_name;
01225   char* fname;
01226   posix_header* blok = 0;
01227   unsigned long count = 0;
01228   struct super_block* s = filp->f_dentry->d_inode->i_sb;
01229 
01230   if ( !(blok = (posix_header*) kmalloc(sizeof(posix_header), GFP_KERNEL)) ) {
01231       goto EOut4;
01232   }
01233 
01234   //nejprve musim nacist jmeno adresare (v taru se vse pamatuje uplnou cestou)
01235   //a pozici, kde mam zacit nacitat soubory
01236   if (filp->f_dentry->d_inode->i_ino == TARFS_ROOT_INO) {
01237 
01238     //pokud je to rootovsky adresar
01239     dir_name = (char*) kmalloc(sizeof(char), GFP_KERNEL);
01240     dir_name[0] = 0;
01241     dsize = 0;
01242     pos =  0;
01243 
01244   } else {
01245 
01246     pos = OFFSET_BY_INO(filp->f_dentry->d_inode->i_ino);
01247     if (!read_block(s, pos, blok)) {
01248       goto EOut3;
01249     }
01250 
01251     if (blok->typeflag != 'L' && blok->typeflag != DIRTYPE) {
01252       //pokud to neni adresar (nebo alespon potencialne adresar)
01253       goto EOut3;
01254     }
01255 
01256     //jestlize ma adresar dlouhe jmeno
01257     if (blok->typeflag == 'L') {
01258         dsize = oct_to_dec(blok->size, TARFS_NUMLENGTH);
01259         dsize--;
01260         if (!pom_read_name(s, &dir_name, dsize, pos++)) {
01261           goto EOut3;
01262         }
01263         pos += hcc(dsize, TARFS_BLKSIZE);
01264         //jeste musim overit, ze jmeno, ktere jsem nacetl patri opravdu adresari
01265         if ( !read_block(s, pos, blok) ) {
01266           goto EOut2;
01267         }
01268         if (blok->typeflag != DIRTYPE) {
01269           goto EOut2;
01270         }
01271         pos++;//za ten prave nacteny blok
01272 
01273     } else {
01274     
01275       dsize = short_name_size(blok->name); //nulu na konec nedam
01276       if ( !(dir_name = (char*) kmalloc(dsize * sizeof(char), GFP_KERNEL)) ) {
01277         goto EOut3;
01278       }
01279       memcpy(dir_name, blok->name, (unsigned int) dsize);
01280       pos++;
01281     }
01282   }
01283   // docetl jsem jmeno adresare a pozici,
01284   // kde by meli zacit soubory toho adresare(pokud nejake ma)
01285 
01286   //zjistuji, jestli uz jsem nejake soubory nacetl a pokud ano, tak zmenim pos
01287   //ve f_pos je ulozen offset naposledy nactene polozky
01288   if (filp->f_pos > 0 && filp->f_pos < TARFS_PARENTDIR_FPOS && filp->f_pos <= (pos + 1)) {
01289     //chyba - to nelze
01290     goto EOut2;
01291   }
01292   
01293   // Pridam adresar "."
01294   if (filp->f_pos == 0) {
01295     //prvni cteni, musim si zapamatovat link na "."
01296     if (filldir(dirent, ".", 1, 0, filp->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
01297        //dalsi soubory uz nemam cist
01298        goto Return_Count2;  // v count je 0
01299     }
01300     count++;
01301     filp->f_pos = TARFS_THISDIR_FPOS;
01302   }
01303   
01304   // Pridam adresar ".."
01305   if (filp->f_pos == TARFS_THISDIR_FPOS) {
01306     //zatim jsem nacetl '.', musim si zapamatovat link na ".."
01307     i = filp->f_dentry->d_parent->d_inode->i_ino;    // ne-root
01308 
01309     if (filldir(dirent, "..", 2, 0, i, DT_DIR) < 0) {
01310        //dalsi soubory uz nemam cist
01311        goto Return_Count2;
01312     }
01313 
01314     count++;
01315     filp->f_pos = TARFS_PARENTDIR_FPOS;
01316   }
01317 
01318   if (filp->f_pos != TARFS_PARENTDIR_FPOS) {
01319     //uz jsem neco precetl, takze upravim pos
01320     //nejprve se dostanu na hlavni header block naposledy cteneho souboru
01321     pos = skip_blocks(s, (unsigned long) filp->f_pos - 1);
01322 
01323     if (pos == TARFS_EVAL || !read_block(s, pos, blok) || !is_tar(blok)) {
01324       goto EOut2;
01325     }
01326     pos += hcc(oct_to_dec(blok->size, TARFS_NUMLENGTH), TARFS_BLKSIZE) + 1;
01327   }
01328 
01329 
01330   //ted vim, kde zacit cist jmena souboru (od pos)
01331   while (read_block(s, pos, blok) && is_tar(blok)) {
01332     unsigned long pom_fsize;
01333     int rv;
01334     unsigned type;
01335 
01336     switch(blok->typeflag) {
01337 
01338       default:
01339         goto EOut2;
01340         break;
01341 
01342       case 'L' :
01343         //dalsi blok bude jmeno souboru, pak bude nasledovat ten soubor
01344         fsize = oct_to_dec(blok->size, TARFS_NUMLENGTH) - 1; //tar - nevim proc to zvetsuje o 1
01345 
01346         if (!pom_read_name(s, &fname, fsize, pos + 1)) {
01347           goto EOut2;
01348         }
01349 
01350         if ( !(rv = is_right_prefix(dir_name, dsize, fname, fsize)) ) {
01351             //dalsi soubory uz nejsou soucasti tohohle adresare
01352             //nechavam filp->f_pos nedotceno
01353             goto Return_Count1;
01354         }
01355 
01356         if (rv < 0) {
01357           //zanoril jsem se moc, musim preskakat ty soubory
01358           pos += hcc(fsize, TARFS_BLKSIZE) + 1;
01359 
01360           if( !read_block(s, pos, blok) || !is_tar(blok) ) {
01361             goto EOut1;
01362           }
01363 
01364           filp->f_pos = (loff_t) pos + 1; //abych ho uz nezkoumal
01365           fsize = oct_to_dec(blok->size, TARFS_NUMLENGTH);
01366           pos += hcc(fsize, TARFS_BLKSIZE) + 1;
01367           break;
01368         }
01369 
01370         if (fname[fsize - 1] == '/') {
01371           pom_fsize = fsize - 1;
01372         } else {
01373           pom_fsize = fsize;
01374         }
01375 
01376         //posunu se na hlavni blok souboru;
01377         pos += hcc(fsize, TARFS_BLKSIZE) + 1;
01378 
01379         if ( !read_block(s, pos, blok) || !is_tar(blok) ) {
01380             goto EOut1;
01381         }
01382 
01383         if (get_type(blok, &type) < 0) {
01384           goto EOut1;
01385         }
01386 
01387         //pridavam jmeno
01388         if (filldir(dirent, fname + dsize, pom_fsize - dsize, 0, pos + 1, type) < 0) {
01389           //dalsi soubory uz nemam cist
01390           goto Return_Count1;
01391         }
01392 
01393         count++;
01394         filp->f_pos = (loff_t) pos + 1;
01395 
01396         kfree(fname);
01397         fsize = oct_to_dec(blok->size, TARFS_NUMLENGTH);
01398         pos += hcc(fsize,TARFS_BLKSIZE) + 1;
01399         break;
01400 
01401       case 'K' :
01402         // dalsi blok bude jmeno linku, pak bude nasledovat ten link
01403         //takze jen preskocim na dalsi blok
01404         fsize = oct_to_dec(blok->size, TARFS_NUMLENGTH);
01405         pos += hcc(fsize,TARFS_BLKSIZE) + 1;
01406         break;
01407 
01408       case REGTYPE ://normalni soubor - alternativni kod
01409       case AREGTYPE://normalni soubor - preferovany kod
01410       case LNKTYPE ://hardlink
01411       case SYMTYPE ://symlink, vratim info o symlinku
01412       case CHRTYPE :;//znakove zarizeni
01413       case BLKTYPE :;//blokove zarizeni
01414       case DIRTYPE :;//adresar
01415       case FIFOTYPE: //je to pojmenovana pipe
01416         fsize = short_name_size(blok->name);
01417         fname = blok->name;
01418         
01419         if( !(rv = is_right_prefix(dir_name, dsize, fname, fsize)) ) {
01420             //dalsi soubory uz nejsou soucasti tohohle adresare
01421             //nechavam filp->f_pos nedotceno
01422             goto Return_Count2;
01423         }
01424         
01425         if (rv < 0) {
01426           //zanoril jsem se moc, musim preskakat ty soubory
01427           filp->f_pos = (loff_t) pos + 1;//abych ho uz nezkoumal
01428           fsize = oct_to_dec(blok->size, TARFS_NUMLENGTH);
01429           pos += hcc(fsize, TARFS_BLKSIZE) + 1;
01430           break;
01431         }
01432 
01433         if (fname[fsize - 1] == '/') {
01434           pom_fsize = fsize - 1;
01435         } else {
01436           pom_fsize = fsize;
01437         }
01438 
01439         if (get_type(blok, &type) < 0) {
01440           goto EOut2;
01441         }
01442 
01443         //pridavam jmeno
01444         if (filldir(dirent, fname + dsize, pom_fsize - dsize, 0, pos + 1, type) < 0) {
01445           //dalsi soubory uz nemam cist
01446           goto Return_Count2;
01447         }
01448 
01449         count++;
01450         filp->f_pos = (loff_t) pos + 1;
01451 
01452         fsize = oct_to_dec(blok->size, TARFS_NUMLENGTH);
01453         pos += hcc(fsize,TARFS_BLKSIZE) + 1;
01454         break;
01455 
01456     } //end switch
01457   } //end while
01458 
01459 
01460   if (is_nullblock(blok, TARFS_BLKSIZE)) {
01461     goto Return_Count2;
01462   }
01463   goto EOut2;
01464 
01465 
01466 // return
01467 Return_Count1:
01468   kfree(fname);
01469 
01470 Return_Count2:
01471   kfree(blok);
01472   kfree(dir_name);
01473   return count;
01474 
01475 // errors
01476 EOut1:
01477   kfree(fname);
01478 
01479 EOut2:
01480   kfree(dir_name);
01481 
01482 EOut3:
01483   kfree(blok);
01484 
01485 EOut4:
01486   return TARFS_EVAL;
01487 }
01488 
01489 
01499 unsigned long tar_lookup(struct super_block* s, unsigned long ino, const char* fname, unsigned int fsize)
01500 {
01501 
01502   unsigned long pos, fullsize, dsize;
01503   unsigned long ret_val;
01504   posix_header* blok;
01505   char* fullname;//jmeno souboru s celou cestou (v nasem FS, bez / na zacatku)
01506   char* dname;
01507 
01508 
01509   if (ino < 0 || !fname || fsize < 1) {
01510     goto EOut2;
01511   }
01512 
01513   if ( !(blok = (posix_header*) kmalloc(sizeof(posix_header), GFP_KERNEL)) ) {
01514     goto EOut2;
01515   }
01516 
01517   if (ino == TARFS_ROOT_INO) {
01518     //ino je korenovy adresar
01519     if ( !(fullname = (char*) kmalloc(fsize * sizeof(char), GFP_KERNEL)) ) {
01520       goto EOut1;
01521     }
01522     memcpy(fullname, fname, fsize);
01523     fullsize = fsize;
01524     pos = -1;//posune se o dal
01525 
01526   } else {
01527 
01528     pos = OFFSET_BY_INO(ino);
01529     if ( !read_block(s, pos, blok) || !is_tar(blok) ) {
01530       goto EOut1;
01531     }
01532 
01533     //pokud to neni adresar ani potencialne
01534     if (blok->typeflag != 'L' && blok->typeflag != DIRTYPE) {
01535       goto EOut1;
01536     }
01537 
01538     if (blok->typeflag == 'L') {
01539       //pokud to ma dlouhe jmeno
01540       dsize = oct_to_dec(blok->size, TARFS_NUMLENGTH) - 1;
01541 
01542       if (!pom_read_name(s, &dname, dsize, pos + 1 )) {
01543         goto EOut1;
01544       }
01545 
01546       fullsize = dsize + fsize;
01547 
01548       if( !(fullname = (char*) kmalloc(fullsize * sizeof(char), GFP_KERNEL)) ) {
01549         kfree(dname);
01550         goto EOut1;
01551       }
01552 
01553       memcpy(fullname,dname,dsize);
01554       kfree(dname);
01555       memcpy(fullname+dsize,fname,fsize);
01556       pos += hcc(dsize+1,TARFS_BLKSIZE)+1;
01557 
01558       if( !read_block(s, pos, blok) && !is_tar(blok) && blok->typeflag != DIRTYPE ) {
01559         //kdyz to neni adresar (s dlouhym jmenem)
01560         kfree(fullname);
01561         goto EOut1;
01562       }
01563 
01564     } else {
01565       //je to primo adresar
01566       dsize = short_name_size(blok->name);
01567       fullsize = fsize + dsize;
01568 
01569       if ( !(fullname = (char*) kmalloc(fullsize * sizeof(char), GFP_KERNEL)) ) {
01570           goto EOut1;
01571       }
01572 
01573       memcpy(fullname, blok->name, dsize);
01574       memcpy(fullname + dsize, fname, fsize);
01575     }
01576   }
01577 
01578   //ted mam v fullsize delku full path zadaneho souboru
01579   //a v fullname full path zadaneho souboru;
01580   pos++;//skocim na 1.soubor za tim adresarem
01581 
01582 
01583   ret_val = offset_by_name2(s, pos, fullname, fullsize);
01584 
01585   kfree(blok);
01586   kfree(fullname);
01587 
01588   return (ret_val == TARFS_EVAL) ? TARFS_EVAL : (ret_val + 1);
01589 
01590   // errors
01591 EOut1:
01592   kfree(blok);
01593 
01594 EOut2:
01595   return TARFS_EVAL;
01596 }

Generated on Fri May 23 02:10:44 2003 for TarFS by doxygen1.3