00001
00011
00012
00013
00014
00015
00016
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 {
00030 char name[100];
00031 char mode[8];
00032 char uid[8];
00033 char gid[8];
00034 char size[12];
00035 char mtime[12];
00036 char chksum[8];
00037 char typeflag;
00038 char linkname[100];
00039 char magic[6];
00040 char version[2];
00041 char uname[32];
00042 char gname[32];
00043 char devmajor[8];
00044 char devminor[8];
00045 char prefix[155];
00046 char pad [12];
00047 } posix_header;
00048
00049 #define TMAGIC "ustar"
00050 #define TMAGLEN 6
00051 #define TVERSION "00"
00052 #define TVERSLEN 2
00053
00054
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
00066 #define TSUID 04000
00067 #define TSGID 02000
00068 #define TSVTX 01000
00069
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
00102
00103
00104 if (memcmp(blok->magic, TMAGIC, TMAGLEN - 1)) {
00105 return 0;
00106 }
00107
00108
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);
00120
00121
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
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
00199 goto EOut1;
00200 }
00201
00202 switch(blok->typeflag) {
00203 default :
00204 goto EOut1;
00205 break;
00206
00207 case 'L' :
00208 case 'K' :
00209 size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00210 i += hcc(size, TARFS_BLKSIZE);
00211 i++;
00212 break;
00213
00214 case REGTYPE :
00215 case AREGTYPE:
00216 case LNKTYPE :
00217 case SYMTYPE :
00218 case CHRTYPE :;
00219 case BLKTYPE :;
00220 case DIRTYPE :;
00221 case FIFOTYPE:
00222 ret_val = get_root_ino_pom(blok);
00223 kfree(blok);
00224 return ret_val;
00225 break;
00226 }
00227 }
00228
00229
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
00248
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
00263 if (is_nullblock(blok, TARFS_BLKSIZE) && read_block(s, i + 1, blok)) {
00264 if(is_nullblock(blok,TARFS_BLKSIZE)) {
00265 kfree(blok);
00266
00267 return i + 1;
00268 } else {
00269
00270 break;
00271 }
00272 }
00273
00274 break;
00275 }
00276
00277 size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00278
00279 i += hcc(size,TARFS_BLKSIZE);
00280 i++;
00281 }
00282
00283 kfree(blok);
00284
00285 EOut1:
00286
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;
00329 kfree(blok);
00330 return 1;
00331
00332
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;
00360
00361 if (!name || *name == 0) {
00362 return TARFS_EVAL;
00363 }
00364
00365
00366
00367
00368
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
00379 goto EOut1;
00380 }
00381
00382 if (skip) {
00383 size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00384
00385 i += hcc(size, TARFS_BLKSIZE);
00386 i++;
00387 skip = 0;
00388 continue;
00389 }
00390
00391 switch (blok->typeflag) {
00392 default :
00393
00394 goto EOut1;
00395 break;
00396
00397 case 'K' :
00398
00399 size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00400
00401 if (size == 0) {
00402
00403 goto EOut1;
00404 }
00405
00406 size--;
00407
00408
00409 correction = hcc(size,TARFS_BLKSIZE) + 1;
00410 i += hcc(size, TARFS_BLKSIZE);
00411 break;
00412
00413 case 'L' :
00414
00415 size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00416
00417 if (size == 0) {
00418
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
00430 kfree(file_name);
00431 kfree(blok);
00432 return i - correction;
00433 }
00434 if (file_name) {
00435 kfree(file_name);
00436 }
00437 skip = 1;
00438
00439 i += hcc(size, TARFS_BLKSIZE);
00440 correction = 0;
00441 break;
00442 }
00443
00444 case REGTYPE :
00445 case AREGTYPE:
00446 case LNKTYPE :
00447 case SYMTYPE :
00448 case CHRTYPE :;
00449 case BLKTYPE :;
00450 case DIRTYPE :;
00451 case FIFOTYPE:;
00452
00453 if (name_comparator(blok, name, 100)) {
00454
00455 kfree(blok);
00456 return i - correction;
00457 } else {
00458 size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00459
00460 i += hcc(size, TARFS_BLKSIZE);
00461 correction = 0;
00462 break;
00463 }
00464 break;
00465
00466 }
00467 i++;
00468 }
00469
00470
00471 EOut1:
00472 kfree(blok);
00473
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;
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
00512 goto EOut1;
00513 }
00514
00515 if (skip) {
00516 size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00517
00518 i += hcc(size, TARFS_BLKSIZE);
00519 i++;
00520 skip = 0;
00521 continue;
00522 }
00523
00524 switch(blok->typeflag) {
00525
00526 default :
00527
00528 goto EOut1;
00529 break;
00530
00531 case 'K' :
00532
00533 size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00534
00535 if (size == 0) {
00536 goto EOut1;
00537 }
00538
00539 size--;
00540
00541
00542 correction = hcc(size, TARFS_BLKSIZE) + 1;
00543 i += hcc(size, TARFS_BLKSIZE);
00544 break;
00545
00546 case 'L' :
00547
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
00564 kfree(file_name);
00565 kfree(blok);
00566 return i - correction;
00567 }
00568
00569 if (file_name) {
00570 kfree(file_name);
00571 }
00572
00573
00574 skip = 1;
00575
00576
00577 i += hcc(size, TARFS_BLKSIZE);
00578 correction = 0;
00579 break;
00580 }
00581
00582 case REGTYPE :
00583 case AREGTYPE:
00584 case LNKTYPE :
00585 case SYMTYPE :
00586 case CHRTYPE :;
00587 case BLKTYPE :;
00588 case DIRTYPE :;
00589 case FIFOTYPE:;
00590
00591 size = short_name_size(blok->name);
00592
00593 if (name_comparator2(blok->name, name, size, fsize)) {
00594
00595 kfree(blok);
00596 return i - correction;
00597 } else {
00598 size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00599
00600 i += hcc(size, TARFS_BLKSIZE);
00601 correction = 0;
00602 }
00603 break;
00604
00605 }
00606 i++;
00607 }
00608
00609
00610
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
00645 goto EOut1;
00646 }
00647
00648 switch (blok->typeflag) {
00649
00650 default :
00651 goto EOut1;
00652 break;
00653
00654 case 'L' :
00655 case 'K' :
00656 size = oct_to_dec(blok->size, TARFS_NUMLENGTH);
00657 i += hcc(size, TARFS_BLKSIZE) + 1;
00658 break;
00659
00660 case REGTYPE :
00661 case AREGTYPE:
00662 case LNKTYPE :
00663 case SYMTYPE :
00664 case CHRTYPE :;
00665 case BLKTYPE :;
00666 case DIRTYPE :;
00667 case FIFOTYPE:
00668 kfree(blok);
00669 return i;
00670 break;
00671 }
00672 }
00673
00674
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
00695 *type = DT_UNKNOWN;
00696 return -1;
00697 break;
00698
00699 case REGTYPE :
00700 case AREGTYPE:
00701 case LNKTYPE :
00702 *type = DT_REG;
00703 break;
00704
00705 case SYMTYPE :
00706 *type = DT_LNK;
00707 break;
00708
00709 case CHRTYPE :
00710 *type = DT_CHR;
00711 break;
00712
00713 case BLKTYPE :
00714 *type = DT_BLK;
00715 break;
00716
00717 case DIRTYPE :
00718 *type = DT_DIR;
00719 break;
00720
00721 case FIFOTYPE:
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
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
00768 offset = skip_blocks(s, offset);
00769 if (offset == TARFS_EVAL) {
00770 goto EOut1;
00771 }
00772 break;
00773
00774 case 'K' :
00775
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
00791 case AREGTYPE:
00792
00793
00794 ret_type = S_IFREG;
00795 should_continue = 0;
00796 break;
00797
00798 case LNKTYPE :
00799
00800 if (!link_name) {
00801
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);
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
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
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
00848
00849 ret_type = S_IFIFO;
00850 should_continue = 0;
00851 break;
00852
00853 case DIRTYPE :
00854
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
00871
00872
00873
00874 inode->i_ctime = (time_t) inode->i_atime = inode->i_mtime = oct_to_dec(blok->mtime, TARFS_NUMLENGTH);
00875
00876
00877 if (blok->typeflag != SYMTYPE) {
00878 inode->i_size = (loff_t) oct_to_dec(blok->size, TARFS_NUMLENGTH);
00879 }
00880
00881
00882 inode->i_gid = (gid_t) oct_to_dec(blok->gid, 7);
00883
00884 inode->i_uid = (uid_t) oct_to_dec(blok->uid, 7);
00885
00886 inode->i_mode = (umode_t) oct_to_dec(blok->mode, 7);
00887
00888
00889 inode->i_nlink = 1;
00890
00891 kfree(blok);
00892 return ret_type;
00893
00894
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
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
00942 offset = skip_blocks(s, offset);
00943 if (offset == TARFS_EVAL) {
00944 goto EOut1;
00945 }
00946 break;
00947
00948 case 'K' :
00949
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
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 :
00990 case AREGTYPE:
00991 case SYMTYPE :
00992 case CHRTYPE :
00993 case BLKTYPE :
00994 case FIFOTYPE:
00995 case DIRTYPE :
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
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
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
01114 if (inode->i_ino == TARFS_ROOT_INO) {
01115 return 0;
01116 }
01117
01118
01119
01120 diff = (unsigned long) (inode->i_size - offset);
01121 diff = (unsigned long) ((diff > PAGE_SIZE) ? PAGE_SIZE : diff);
01122
01123
01124 if (!diff) {
01125 return 0;
01126 }
01127
01128
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++;
01149
01150 start_shift = (unsigned long) (offset / TARFS_BLKSIZE);
01151 end_shift = hcc((unsigned long) offset + diff, TARFS_BLKSIZE);
01152
01153
01154 if (offset % TARFS_BLKSIZE == 0) {
01155
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
01163 memset((void*) (buffer + diff), 0, (unsigned int) (PAGE_SIZE - diff));
01164 kfree(blok);
01165 return 1;
01166 }
01167
01168
01169
01170
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
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
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
01191 memset((void*) (buffer + diff), 0, (unsigned int) (PAGE_SIZE - diff));
01192
01193
01194 kfree(blok);
01195 return 1;
01196
01197
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
01235
01236 if (filp->f_dentry->d_inode->i_ino == TARFS_ROOT_INO) {
01237
01238
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
01253 goto EOut3;
01254 }
01255
01256
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
01265 if ( !read_block(s, pos, blok) ) {
01266 goto EOut2;
01267 }
01268 if (blok->typeflag != DIRTYPE) {
01269 goto EOut2;
01270 }
01271 pos++;
01272
01273 } else {
01274
01275 dsize = short_name_size(blok->name);
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
01284
01285
01286
01287
01288 if (filp->f_pos > 0 && filp->f_pos < TARFS_PARENTDIR_FPOS && filp->f_pos <= (pos + 1)) {
01289
01290 goto EOut2;
01291 }
01292
01293
01294 if (filp->f_pos == 0) {
01295
01296 if (filldir(dirent, ".", 1, 0, filp->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
01297
01298 goto Return_Count2;
01299 }
01300 count++;
01301 filp->f_pos = TARFS_THISDIR_FPOS;
01302 }
01303
01304
01305 if (filp->f_pos == TARFS_THISDIR_FPOS) {
01306
01307 i = filp->f_dentry->d_parent->d_inode->i_ino;
01308
01309 if (filldir(dirent, "..", 2, 0, i, DT_DIR) < 0) {
01310
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
01320
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
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
01344 fsize = oct_to_dec(blok->size, TARFS_NUMLENGTH) - 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
01352
01353 goto Return_Count1;
01354 }
01355
01356 if (rv < 0) {
01357
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;
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
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
01388 if (filldir(dirent, fname + dsize, pom_fsize - dsize, 0, pos + 1, type) < 0) {
01389
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
01403
01404 fsize = oct_to_dec(blok->size, TARFS_NUMLENGTH);
01405 pos += hcc(fsize,TARFS_BLKSIZE) + 1;
01406 break;
01407
01408 case REGTYPE :
01409 case AREGTYPE:
01410 case LNKTYPE :
01411 case SYMTYPE :
01412 case CHRTYPE :;
01413 case BLKTYPE :;
01414 case DIRTYPE :;
01415 case FIFOTYPE:
01416 fsize = short_name_size(blok->name);
01417 fname = blok->name;
01418
01419 if( !(rv = is_right_prefix(dir_name, dsize, fname, fsize)) ) {
01420
01421
01422 goto Return_Count2;
01423 }
01424
01425 if (rv < 0) {
01426
01427 filp->f_pos = (loff_t) pos + 1;
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
01444 if (filldir(dirent, fname + dsize, pom_fsize - dsize, 0, pos + 1, type) < 0) {
01445
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 }
01457 }
01458
01459
01460 if (is_nullblock(blok, TARFS_BLKSIZE)) {
01461 goto Return_Count2;
01462 }
01463 goto EOut2;
01464
01465
01466
01467 Return_Count1:
01468 kfree(fname);
01469
01470 Return_Count2:
01471 kfree(blok);
01472 kfree(dir_name);
01473 return count;
01474
01475
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;
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
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;
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
01534 if (blok->typeflag != 'L' && blok->typeflag != DIRTYPE) {
01535 goto EOut1;
01536 }
01537
01538 if (blok->typeflag == 'L') {
01539
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
01560 kfree(fullname);
01561 goto EOut1;
01562 }
01563
01564 } else {
01565
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
01579
01580 pos++;
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
01591 EOut1:
01592 kfree(blok);
01593
01594 EOut2:
01595 return TARFS_EVAL;
01596 }