Fossil SCM
Change the tarball generator to use the USTAR tar format.
Commit
1b7777b9eeb3b2950fe3c705117ebb069bac35c3
Parent
d5d676f0c7f37d6…
1 file changed
+26
-9
+26
-9
| --- src/tar.c | ||
| +++ src/tar.c | ||
| @@ -26,24 +26,27 @@ | ||
| 26 | 26 | ** State information for the tarball builder. |
| 27 | 27 | */ |
| 28 | 28 | static struct tarball_t { |
| 29 | 29 | unsigned char *aHdr; /* Space for building headers */ |
| 30 | 30 | char *zSpaces; /* Spaces for padding */ |
| 31 | + char *zPrevDir; /* Name of directory for previous entry */ | |
| 31 | 32 | } tball; |
| 32 | 33 | |
| 33 | 34 | /* |
| 34 | 35 | ** Begin the process of generating a tarball. |
| 35 | 36 | ** |
| 36 | 37 | ** Initialize the GZIP compressor and the table of directory names. |
| 37 | 38 | */ |
| 38 | 39 | static void tar_begin(void){ |
| 39 | 40 | assert( tball.aHdr==0 ); |
| 40 | - tball.aHdr = fossil_malloc(1024); | |
| 41 | + tball.aHdr = fossil_malloc(512+512+256); | |
| 42 | + memset(tball.aHdr, 0, 512+512+256); | |
| 41 | 43 | tball.zSpaces = (char*)&tball.aHdr[512]; |
| 42 | - memset(tball.aHdr, 0, 512); | |
| 44 | + tball.zPrevDir = (char*)&tball.zSpaces[512]; | |
| 43 | 45 | memcpy(&tball.aHdr[108], "0000000", 8); /* Owner ID */ |
| 44 | 46 | memcpy(&tball.aHdr[116], "0000000", 8); /* Group ID */ |
| 47 | + memcpy(&tball.aHdr[257], "ustar ", 7); /* Format */ | |
| 45 | 48 | gzip_begin(); |
| 46 | 49 | db_multi_exec( |
| 47 | 50 | "CREATE TEMP TABLE dir(name UNIQUE);" |
| 48 | 51 | ); |
| 49 | 52 | } |
| @@ -60,13 +63,19 @@ | ||
| 60 | 63 | int iSize, /* Size of the object in bytes */ |
| 61 | 64 | int iType /* Type of object. 0==file. 5==directory */ |
| 62 | 65 | ){ |
| 63 | 66 | unsigned int cksum = 0; |
| 64 | 67 | int i; |
| 65 | - assert( nName<100 ); | |
| 66 | - memcpy(tball.aHdr, zName, nName); | |
| 67 | - memset(&tball.aHdr[nName], 0, 100-nName); | |
| 68 | + if( nName>100 ){ | |
| 69 | + memcpy(&tball.aHdr[345], zName, nName-100); | |
| 70 | + memcpy(tball.aHdr, &zName[nName-100], 100); | |
| 71 | + memset(&tball.aHdr[245+nName], 0, 267-nName); | |
| 72 | + }else{ | |
| 73 | + memcpy(tball.aHdr, zName, nName); | |
| 74 | + memset(&tball.aHdr[nName], 0, 100-nName); | |
| 75 | + memset(&tball.aHdr[345], 0, 167); | |
| 76 | + } | |
| 68 | 77 | sqlite3_snprintf(8, (char*)&tball.aHdr[100], "%07o", iMode); |
| 69 | 78 | sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize); |
| 70 | 79 | sqlite3_snprintf(12, (char*)&tball.aHdr[136], "%011o", mTime); |
| 71 | 80 | memset(&tball.aHdr[148], ' ', 8); |
| 72 | 81 | tball.aHdr[156] = iType + '0'; |
| @@ -86,14 +95,17 @@ | ||
| 86 | 95 | unsigned int mTime /* Modification time */ |
| 87 | 96 | ){ |
| 88 | 97 | int i; |
| 89 | 98 | for(i=nName-1; i>0 && zName[i]!='/'; i--){} |
| 90 | 99 | if( i<=0 ) return; |
| 100 | + if( tball.zPrevDir[i]==0 && memcmp(tball.zPrevDir, zName, i)==0 ) return; | |
| 91 | 101 | db_multi_exec("INSERT OR IGNORE INTO dir VALUES('%.*q')", i, zName); |
| 92 | 102 | if( sqlite3_changes(g.db)==0 ) return; |
| 93 | 103 | tar_add_directory_of(zName, i-1, mTime); |
| 94 | 104 | tar_add_header(zName, i, 0755, mTime, 0, 5); |
| 105 | + memcpy(tball.zPrevDir, zName, i); | |
| 106 | + tball.zPrevDir[i] = 0; | |
| 95 | 107 | } |
| 96 | 108 | |
| 97 | 109 | /* |
| 98 | 110 | ** Add a single file to the growing tarball. |
| 99 | 111 | */ |
| @@ -105,16 +117,21 @@ | ||
| 105 | 117 | ){ |
| 106 | 118 | int nName = strlen(zName); |
| 107 | 119 | int n = blob_size(pContent); |
| 108 | 120 | int lastPage; |
| 109 | 121 | |
| 122 | + if( nName>=250 ){ | |
| 123 | + fossil_fatal("name too long for ustar format: \"%s\"", zName); | |
| 124 | + } | |
| 110 | 125 | tar_add_directory_of(zName, nName, mTime); |
| 111 | 126 | tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, 0); |
| 112 | - gzip_step(blob_buffer(pContent), n); | |
| 113 | - lastPage = n % 512; | |
| 114 | - if( lastPage!=0 ){ | |
| 115 | - gzip_step(tball.zSpaces, 512 - lastPage); | |
| 127 | + if( n ){ | |
| 128 | + gzip_step(blob_buffer(pContent), n); | |
| 129 | + lastPage = n % 512; | |
| 130 | + if( lastPage!=0 ){ | |
| 131 | + gzip_step(tball.zSpaces, 512 - lastPage); | |
| 132 | + } | |
| 116 | 133 | } |
| 117 | 134 | } |
| 118 | 135 | |
| 119 | 136 | /* |
| 120 | 137 | ** Finish constructing the tarball. Put the content of the tarball |
| 121 | 138 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -26,24 +26,27 @@ | |
| 26 | ** State information for the tarball builder. |
| 27 | */ |
| 28 | static struct tarball_t { |
| 29 | unsigned char *aHdr; /* Space for building headers */ |
| 30 | char *zSpaces; /* Spaces for padding */ |
| 31 | } tball; |
| 32 | |
| 33 | /* |
| 34 | ** Begin the process of generating a tarball. |
| 35 | ** |
| 36 | ** Initialize the GZIP compressor and the table of directory names. |
| 37 | */ |
| 38 | static void tar_begin(void){ |
| 39 | assert( tball.aHdr==0 ); |
| 40 | tball.aHdr = fossil_malloc(1024); |
| 41 | tball.zSpaces = (char*)&tball.aHdr[512]; |
| 42 | memset(tball.aHdr, 0, 512); |
| 43 | memcpy(&tball.aHdr[108], "0000000", 8); /* Owner ID */ |
| 44 | memcpy(&tball.aHdr[116], "0000000", 8); /* Group ID */ |
| 45 | gzip_begin(); |
| 46 | db_multi_exec( |
| 47 | "CREATE TEMP TABLE dir(name UNIQUE);" |
| 48 | ); |
| 49 | } |
| @@ -60,13 +63,19 @@ | |
| 60 | int iSize, /* Size of the object in bytes */ |
| 61 | int iType /* Type of object. 0==file. 5==directory */ |
| 62 | ){ |
| 63 | unsigned int cksum = 0; |
| 64 | int i; |
| 65 | assert( nName<100 ); |
| 66 | memcpy(tball.aHdr, zName, nName); |
| 67 | memset(&tball.aHdr[nName], 0, 100-nName); |
| 68 | sqlite3_snprintf(8, (char*)&tball.aHdr[100], "%07o", iMode); |
| 69 | sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize); |
| 70 | sqlite3_snprintf(12, (char*)&tball.aHdr[136], "%011o", mTime); |
| 71 | memset(&tball.aHdr[148], ' ', 8); |
| 72 | tball.aHdr[156] = iType + '0'; |
| @@ -86,14 +95,17 @@ | |
| 86 | unsigned int mTime /* Modification time */ |
| 87 | ){ |
| 88 | int i; |
| 89 | for(i=nName-1; i>0 && zName[i]!='/'; i--){} |
| 90 | if( i<=0 ) return; |
| 91 | db_multi_exec("INSERT OR IGNORE INTO dir VALUES('%.*q')", i, zName); |
| 92 | if( sqlite3_changes(g.db)==0 ) return; |
| 93 | tar_add_directory_of(zName, i-1, mTime); |
| 94 | tar_add_header(zName, i, 0755, mTime, 0, 5); |
| 95 | } |
| 96 | |
| 97 | /* |
| 98 | ** Add a single file to the growing tarball. |
| 99 | */ |
| @@ -105,16 +117,21 @@ | |
| 105 | ){ |
| 106 | int nName = strlen(zName); |
| 107 | int n = blob_size(pContent); |
| 108 | int lastPage; |
| 109 | |
| 110 | tar_add_directory_of(zName, nName, mTime); |
| 111 | tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, 0); |
| 112 | gzip_step(blob_buffer(pContent), n); |
| 113 | lastPage = n % 512; |
| 114 | if( lastPage!=0 ){ |
| 115 | gzip_step(tball.zSpaces, 512 - lastPage); |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | /* |
| 120 | ** Finish constructing the tarball. Put the content of the tarball |
| 121 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -26,24 +26,27 @@ | |
| 26 | ** State information for the tarball builder. |
| 27 | */ |
| 28 | static struct tarball_t { |
| 29 | unsigned char *aHdr; /* Space for building headers */ |
| 30 | char *zSpaces; /* Spaces for padding */ |
| 31 | char *zPrevDir; /* Name of directory for previous entry */ |
| 32 | } tball; |
| 33 | |
| 34 | /* |
| 35 | ** Begin the process of generating a tarball. |
| 36 | ** |
| 37 | ** Initialize the GZIP compressor and the table of directory names. |
| 38 | */ |
| 39 | static void tar_begin(void){ |
| 40 | assert( tball.aHdr==0 ); |
| 41 | tball.aHdr = fossil_malloc(512+512+256); |
| 42 | memset(tball.aHdr, 0, 512+512+256); |
| 43 | tball.zSpaces = (char*)&tball.aHdr[512]; |
| 44 | tball.zPrevDir = (char*)&tball.zSpaces[512]; |
| 45 | memcpy(&tball.aHdr[108], "0000000", 8); /* Owner ID */ |
| 46 | memcpy(&tball.aHdr[116], "0000000", 8); /* Group ID */ |
| 47 | memcpy(&tball.aHdr[257], "ustar ", 7); /* Format */ |
| 48 | gzip_begin(); |
| 49 | db_multi_exec( |
| 50 | "CREATE TEMP TABLE dir(name UNIQUE);" |
| 51 | ); |
| 52 | } |
| @@ -60,13 +63,19 @@ | |
| 63 | int iSize, /* Size of the object in bytes */ |
| 64 | int iType /* Type of object. 0==file. 5==directory */ |
| 65 | ){ |
| 66 | unsigned int cksum = 0; |
| 67 | int i; |
| 68 | if( nName>100 ){ |
| 69 | memcpy(&tball.aHdr[345], zName, nName-100); |
| 70 | memcpy(tball.aHdr, &zName[nName-100], 100); |
| 71 | memset(&tball.aHdr[245+nName], 0, 267-nName); |
| 72 | }else{ |
| 73 | memcpy(tball.aHdr, zName, nName); |
| 74 | memset(&tball.aHdr[nName], 0, 100-nName); |
| 75 | memset(&tball.aHdr[345], 0, 167); |
| 76 | } |
| 77 | sqlite3_snprintf(8, (char*)&tball.aHdr[100], "%07o", iMode); |
| 78 | sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize); |
| 79 | sqlite3_snprintf(12, (char*)&tball.aHdr[136], "%011o", mTime); |
| 80 | memset(&tball.aHdr[148], ' ', 8); |
| 81 | tball.aHdr[156] = iType + '0'; |
| @@ -86,14 +95,17 @@ | |
| 95 | unsigned int mTime /* Modification time */ |
| 96 | ){ |
| 97 | int i; |
| 98 | for(i=nName-1; i>0 && zName[i]!='/'; i--){} |
| 99 | if( i<=0 ) return; |
| 100 | if( tball.zPrevDir[i]==0 && memcmp(tball.zPrevDir, zName, i)==0 ) return; |
| 101 | db_multi_exec("INSERT OR IGNORE INTO dir VALUES('%.*q')", i, zName); |
| 102 | if( sqlite3_changes(g.db)==0 ) return; |
| 103 | tar_add_directory_of(zName, i-1, mTime); |
| 104 | tar_add_header(zName, i, 0755, mTime, 0, 5); |
| 105 | memcpy(tball.zPrevDir, zName, i); |
| 106 | tball.zPrevDir[i] = 0; |
| 107 | } |
| 108 | |
| 109 | /* |
| 110 | ** Add a single file to the growing tarball. |
| 111 | */ |
| @@ -105,16 +117,21 @@ | |
| 117 | ){ |
| 118 | int nName = strlen(zName); |
| 119 | int n = blob_size(pContent); |
| 120 | int lastPage; |
| 121 | |
| 122 | if( nName>=250 ){ |
| 123 | fossil_fatal("name too long for ustar format: \"%s\"", zName); |
| 124 | } |
| 125 | tar_add_directory_of(zName, nName, mTime); |
| 126 | tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, 0); |
| 127 | if( n ){ |
| 128 | gzip_step(blob_buffer(pContent), n); |
| 129 | lastPage = n % 512; |
| 130 | if( lastPage!=0 ){ |
| 131 | gzip_step(tball.zSpaces, 512 - lastPage); |
| 132 | } |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | /* |
| 137 | ** Finish constructing the tarball. Put the content of the tarball |
| 138 |