Fossil SCM
Enhance the 'reconstruct' command to set the correct hash policy (SHA1 or SHA3-256) for artifacts read from disk, inferred from the length of the path name. Also enhance the 'deconstruct' and 'reconstruct' commands with an option to ensure the artifact with RID=1 is a valid manifest. See the wiki page linked to this branch for more information and tests.
Commit
62a00bc7284a82762e40d75df247c1039e318ff13372aec926bc561ad6024e08
Parent
5280c1ab9a05418…
1 file changed
+96
-2
+96
-2
| --- src/rebuild.c | ||
| +++ src/rebuild.c | ||
| @@ -182,11 +182,14 @@ | ||
| 182 | 182 | static int processCnt; /* Number processed so far */ |
| 183 | 183 | static int ttyOutput; /* Do progress output */ |
| 184 | 184 | static Bag bagDone; /* Bag of records rebuilt */ |
| 185 | 185 | |
| 186 | 186 | static char *zFNameFormat; /* Format string for filenames on deconstruct */ |
| 187 | +static int cchFNamePrefix; /* Length of directory prefix in zFNameFormat */ | |
| 188 | +static char *zDestDir; /* Destination directory on deconstruct */ | |
| 187 | 189 | static int prefixLength; /* Length of directory prefix for deconstruct */ |
| 190 | +static int fKeepRid1; /* Flag to preserve RID=1 on de- and reconstruct */ | |
| 188 | 191 | |
| 189 | 192 | |
| 190 | 193 | /* |
| 191 | 194 | ** Draw the percent-complete message. |
| 192 | 195 | ** The input is actually the permill complete. |
| @@ -274,10 +277,21 @@ | ||
| 274 | 277 | /* We are doing "fossil deconstruct" */ |
| 275 | 278 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 276 | 279 | char *zFile = mprintf(zFNameFormat /*works-like:"%s:%s"*/, |
| 277 | 280 | zUuid, zUuid+prefixLength); |
| 278 | 281 | blob_write_to_file(pUse,zFile); |
| 282 | + if( rid==1 && fKeepRid1!=0 ){ | |
| 283 | + char *zFnDotRid1 = mprintf("%s/.rid1", zDestDir); | |
| 284 | + char *zFnRid1 = zFile + cchFNamePrefix + 1; /* Skip directory slash */ | |
| 285 | + Blob bFileContents = empty_blob; | |
| 286 | + blob_appendf(&bFileContents, | |
| 287 | + "# The file holding the artifact with RID=1\n" | |
| 288 | + "%s\n", zFnRid1); | |
| 289 | + blob_write_to_file(&bFileContents, zFnDotRid1); | |
| 290 | + blob_reset(&bFileContents); | |
| 291 | + free(zFnDotRid1); | |
| 292 | + } | |
| 279 | 293 | free(zFile); |
| 280 | 294 | free(zUuid); |
| 281 | 295 | blob_reset(pUse); |
| 282 | 296 | } |
| 283 | 297 | assert( blob_is_reset(pUse) ); |
| @@ -931,11 +945,50 @@ | ||
| 931 | 945 | struct dirent *pEntry; |
| 932 | 946 | Blob aContent; /* content of the just read artifact */ |
| 933 | 947 | static int nFileRead = 0; |
| 934 | 948 | void *zUnicodePath; |
| 935 | 949 | char *zUtf8Name; |
| 950 | + static int recursionLevel = 0; /* Bookkeeping about the recursion level */ | |
| 951 | + static char *zFnRid1 = 0; /* The file holding the artifact with RID=1 */ | |
| 952 | + static int cchPathInitial = 0; /* The length of zPath on first recursion */ | |
| 936 | 953 | |
| 954 | + recursionLevel++; | |
| 955 | + if( recursionLevel==1 ){ | |
| 956 | + cchPathInitial = strlen(zPath); | |
| 957 | + if( fKeepRid1!=0 ){ | |
| 958 | + char *zFnDotRid1 = mprintf("%s/.rid1", zPath); | |
| 959 | + Blob bFileContents; | |
| 960 | + if( blob_read_from_file(&bFileContents, zFnDotRid1, ExtFILE)!=-1 ){ | |
| 961 | + Blob line, value; | |
| 962 | + while( blob_line(&bFileContents, &line)>0 ){ | |
| 963 | + if( blob_token(&line, &value)==0 ) continue; /* Empty line */ | |
| 964 | + if( blob_buffer(&value)[0]=='#' ) continue; /* Comment */ | |
| 965 | + blob_trim(&value); | |
| 966 | + zFnRid1 = mprintf("%s/%s", zPath, blob_str(&value)); | |
| 967 | + break; | |
| 968 | + } | |
| 969 | + blob_reset(&bFileContents); | |
| 970 | + if( zFnRid1 ){ | |
| 971 | + if( blob_read_from_file(&aContent, zFnRid1, ExtFILE)==-1 ){ | |
| 972 | + fossil_fatal("some unknown error occurred while reading \"%s\"", | |
| 973 | + zFnRid1); | |
| 974 | + }else{ | |
| 975 | + recon_set_hash_policy(0, zFnRid1); | |
| 976 | + content_put(&aContent); | |
| 977 | + recon_restore_hash_policy(); | |
| 978 | + blob_reset(&aContent); | |
| 979 | + fossil_print("\r%d", ++nFileRead); | |
| 980 | + fflush(stdout); | |
| 981 | + } | |
| 982 | + }else{ | |
| 983 | + fossil_fatal("an error occurred while reading or parsing \"%s\"", | |
| 984 | + zFnDotRid1); | |
| 985 | + } | |
| 986 | + } | |
| 987 | + free(zFnDotRid1); | |
| 988 | + } | |
| 989 | + } | |
| 937 | 990 | zUnicodePath = fossil_utf8_to_path(zPath, 1); |
| 938 | 991 | d = opendir(zUnicodePath); |
| 939 | 992 | if( d ){ |
| 940 | 993 | while( (pEntry=readdir(d))!=0 ){ |
| 941 | 994 | Blob path; |
| @@ -953,18 +1006,20 @@ | ||
| 953 | 1006 | #else |
| 954 | 1007 | if( file_isdir(zSubpath, ExtFILE)==1 ) |
| 955 | 1008 | #endif |
| 956 | 1009 | { |
| 957 | 1010 | recon_read_dir(zSubpath); |
| 958 | - }else{ | |
| 1011 | + }else if( fossil_strcmp(zSubpath, zFnRid1)!=0 ){ | |
| 959 | 1012 | blob_init(&path, 0, 0); |
| 960 | 1013 | blob_appendf(&path, "%s", zSubpath); |
| 961 | 1014 | if( blob_read_from_file(&aContent, blob_str(&path), ExtFILE)==-1 ){ |
| 962 | 1015 | fossil_fatal("some unknown error occurred while reading \"%s\"", |
| 963 | 1016 | blob_str(&path)); |
| 964 | 1017 | } |
| 1018 | + recon_set_hash_policy(cchPathInitial, blob_str(&path)); | |
| 965 | 1019 | content_put(&aContent); |
| 1020 | + recon_restore_hash_policy(); | |
| 966 | 1021 | blob_reset(&path); |
| 967 | 1022 | blob_reset(&aContent); |
| 968 | 1023 | fossil_print("\r%d", ++nFileRead); |
| 969 | 1024 | fflush(stdout); |
| 970 | 1025 | } |
| @@ -974,10 +1029,49 @@ | ||
| 974 | 1029 | }else { |
| 975 | 1030 | fossil_fatal("encountered error %d while trying to open \"%s\".", |
| 976 | 1031 | errno, g.argv[3]); |
| 977 | 1032 | } |
| 978 | 1033 | fossil_path_free(zUnicodePath); |
| 1034 | + if( recursionLevel==1 && zFnRid1!=0 ) free(zFnRid1); | |
| 1035 | + recursionLevel--; | |
| 1036 | +} | |
| 1037 | + | |
| 1038 | +/* | |
| 1039 | +** Helper functions called from recon_read_dir() to set and restore the correct | |
| 1040 | +** hash policy for an artifact read from disk, inferred from the length of the | |
| 1041 | +** path name. | |
| 1042 | +*/ | |
| 1043 | +#define HPOLICY_NOTDEFINED -1 | |
| 1044 | +static int saved_eHashPolicy = HPOLICY_NOTDEFINED; | |
| 1045 | + | |
| 1046 | +void recon_set_hash_policy( | |
| 1047 | + const int cchPathPrefix, /* Directory prefix length for zUuidAsFilePath */ | |
| 1048 | + const char *zUuidAsFilePath /* Relative, well-formed, from recon_read_dir() */ | |
| 1049 | +){ | |
| 1050 | + int cchTotal, cchHashPart; | |
| 1051 | + int new_eHashPolicy = HPOLICY_NOTDEFINED; | |
| 1052 | + assert( HNAME_COUNT==2 ); /* Review function if new hashes are implemented. */ | |
| 1053 | + if( zUuidAsFilePath==0 ) return; | |
| 1054 | + cchTotal = strlen(zUuidAsFilePath); | |
| 1055 | + if( cchTotal==0 ) return; | |
| 1056 | + if( cchPathPrefix>=cchTotal) return; | |
| 1057 | + cchHashPart = cchTotal - cchPathPrefix; | |
| 1058 | + if( cchHashPart>=HNAME_LEN_K256 ){ | |
| 1059 | + new_eHashPolicy = HPOLICY_SHA3; | |
| 1060 | + }else if( cchHashPart>=HNAME_LEN_SHA1 ){ | |
| 1061 | + new_eHashPolicy = HPOLICY_SHA1; | |
| 1062 | + } | |
| 1063 | + if( new_eHashPolicy!=HPOLICY_NOTDEFINED ){ | |
| 1064 | + saved_eHashPolicy = g.eHashPolicy; | |
| 1065 | + g.eHashPolicy = new_eHashPolicy; | |
| 1066 | + } | |
| 1067 | +} | |
| 1068 | + | |
| 1069 | +void recon_restore_hash_policy(){ | |
| 1070 | + if( saved_eHashPolicy!=HPOLICY_NOTDEFINED ){ | |
| 1071 | + g.eHashPolicy = saved_eHashPolicy; | |
| 1072 | + } | |
| 979 | 1073 | } |
| 980 | 1074 | |
| 981 | 1075 | /* |
| 982 | 1076 | ** COMMAND: reconstruct* |
| 983 | 1077 | ** |
| @@ -1049,11 +1143,10 @@ | ||
| 1049 | 1143 | ** --private Include private artifacts. |
| 1050 | 1144 | ** |
| 1051 | 1145 | ** See also: rebuild, reconstruct |
| 1052 | 1146 | */ |
| 1053 | 1147 | void deconstruct_cmd(void){ |
| 1054 | - const char *zDestDir; | |
| 1055 | 1148 | const char *zPrefixOpt; |
| 1056 | 1149 | Stmt s; |
| 1057 | 1150 | int privateFlag; |
| 1058 | 1151 | |
| 1059 | 1152 | /* get and check prefix length argument and build format string */ |
| @@ -1092,10 +1185,11 @@ | ||
| 1092 | 1185 | if( prefixLength ){ |
| 1093 | 1186 | zFNameFormat = mprintf("%s/%%.%ds/%%s",zDestDir,prefixLength); |
| 1094 | 1187 | }else{ |
| 1095 | 1188 | zFNameFormat = mprintf("%s/%%s",zDestDir); |
| 1096 | 1189 | } |
| 1190 | + cchFNamePrefix = strlen(zDestDir); | |
| 1097 | 1191 | |
| 1098 | 1192 | bag_init(&bagDone); |
| 1099 | 1193 | ttyOutput = 1; |
| 1100 | 1194 | processCnt = 0; |
| 1101 | 1195 | if (!g.fQuiet) { |
| 1102 | 1196 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -182,11 +182,14 @@ | |
| 182 | static int processCnt; /* Number processed so far */ |
| 183 | static int ttyOutput; /* Do progress output */ |
| 184 | static Bag bagDone; /* Bag of records rebuilt */ |
| 185 | |
| 186 | static char *zFNameFormat; /* Format string for filenames on deconstruct */ |
| 187 | static int prefixLength; /* Length of directory prefix for deconstruct */ |
| 188 | |
| 189 | |
| 190 | /* |
| 191 | ** Draw the percent-complete message. |
| 192 | ** The input is actually the permill complete. |
| @@ -274,10 +277,21 @@ | |
| 274 | /* We are doing "fossil deconstruct" */ |
| 275 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 276 | char *zFile = mprintf(zFNameFormat /*works-like:"%s:%s"*/, |
| 277 | zUuid, zUuid+prefixLength); |
| 278 | blob_write_to_file(pUse,zFile); |
| 279 | free(zFile); |
| 280 | free(zUuid); |
| 281 | blob_reset(pUse); |
| 282 | } |
| 283 | assert( blob_is_reset(pUse) ); |
| @@ -931,11 +945,50 @@ | |
| 931 | struct dirent *pEntry; |
| 932 | Blob aContent; /* content of the just read artifact */ |
| 933 | static int nFileRead = 0; |
| 934 | void *zUnicodePath; |
| 935 | char *zUtf8Name; |
| 936 | |
| 937 | zUnicodePath = fossil_utf8_to_path(zPath, 1); |
| 938 | d = opendir(zUnicodePath); |
| 939 | if( d ){ |
| 940 | while( (pEntry=readdir(d))!=0 ){ |
| 941 | Blob path; |
| @@ -953,18 +1006,20 @@ | |
| 953 | #else |
| 954 | if( file_isdir(zSubpath, ExtFILE)==1 ) |
| 955 | #endif |
| 956 | { |
| 957 | recon_read_dir(zSubpath); |
| 958 | }else{ |
| 959 | blob_init(&path, 0, 0); |
| 960 | blob_appendf(&path, "%s", zSubpath); |
| 961 | if( blob_read_from_file(&aContent, blob_str(&path), ExtFILE)==-1 ){ |
| 962 | fossil_fatal("some unknown error occurred while reading \"%s\"", |
| 963 | blob_str(&path)); |
| 964 | } |
| 965 | content_put(&aContent); |
| 966 | blob_reset(&path); |
| 967 | blob_reset(&aContent); |
| 968 | fossil_print("\r%d", ++nFileRead); |
| 969 | fflush(stdout); |
| 970 | } |
| @@ -974,10 +1029,49 @@ | |
| 974 | }else { |
| 975 | fossil_fatal("encountered error %d while trying to open \"%s\".", |
| 976 | errno, g.argv[3]); |
| 977 | } |
| 978 | fossil_path_free(zUnicodePath); |
| 979 | } |
| 980 | |
| 981 | /* |
| 982 | ** COMMAND: reconstruct* |
| 983 | ** |
| @@ -1049,11 +1143,10 @@ | |
| 1049 | ** --private Include private artifacts. |
| 1050 | ** |
| 1051 | ** See also: rebuild, reconstruct |
| 1052 | */ |
| 1053 | void deconstruct_cmd(void){ |
| 1054 | const char *zDestDir; |
| 1055 | const char *zPrefixOpt; |
| 1056 | Stmt s; |
| 1057 | int privateFlag; |
| 1058 | |
| 1059 | /* get and check prefix length argument and build format string */ |
| @@ -1092,10 +1185,11 @@ | |
| 1092 | if( prefixLength ){ |
| 1093 | zFNameFormat = mprintf("%s/%%.%ds/%%s",zDestDir,prefixLength); |
| 1094 | }else{ |
| 1095 | zFNameFormat = mprintf("%s/%%s",zDestDir); |
| 1096 | } |
| 1097 | |
| 1098 | bag_init(&bagDone); |
| 1099 | ttyOutput = 1; |
| 1100 | processCnt = 0; |
| 1101 | if (!g.fQuiet) { |
| 1102 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -182,11 +182,14 @@ | |
| 182 | static int processCnt; /* Number processed so far */ |
| 183 | static int ttyOutput; /* Do progress output */ |
| 184 | static Bag bagDone; /* Bag of records rebuilt */ |
| 185 | |
| 186 | static char *zFNameFormat; /* Format string for filenames on deconstruct */ |
| 187 | static int cchFNamePrefix; /* Length of directory prefix in zFNameFormat */ |
| 188 | static char *zDestDir; /* Destination directory on deconstruct */ |
| 189 | static int prefixLength; /* Length of directory prefix for deconstruct */ |
| 190 | static int fKeepRid1; /* Flag to preserve RID=1 on de- and reconstruct */ |
| 191 | |
| 192 | |
| 193 | /* |
| 194 | ** Draw the percent-complete message. |
| 195 | ** The input is actually the permill complete. |
| @@ -274,10 +277,21 @@ | |
| 277 | /* We are doing "fossil deconstruct" */ |
| 278 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 279 | char *zFile = mprintf(zFNameFormat /*works-like:"%s:%s"*/, |
| 280 | zUuid, zUuid+prefixLength); |
| 281 | blob_write_to_file(pUse,zFile); |
| 282 | if( rid==1 && fKeepRid1!=0 ){ |
| 283 | char *zFnDotRid1 = mprintf("%s/.rid1", zDestDir); |
| 284 | char *zFnRid1 = zFile + cchFNamePrefix + 1; /* Skip directory slash */ |
| 285 | Blob bFileContents = empty_blob; |
| 286 | blob_appendf(&bFileContents, |
| 287 | "# The file holding the artifact with RID=1\n" |
| 288 | "%s\n", zFnRid1); |
| 289 | blob_write_to_file(&bFileContents, zFnDotRid1); |
| 290 | blob_reset(&bFileContents); |
| 291 | free(zFnDotRid1); |
| 292 | } |
| 293 | free(zFile); |
| 294 | free(zUuid); |
| 295 | blob_reset(pUse); |
| 296 | } |
| 297 | assert( blob_is_reset(pUse) ); |
| @@ -931,11 +945,50 @@ | |
| 945 | struct dirent *pEntry; |
| 946 | Blob aContent; /* content of the just read artifact */ |
| 947 | static int nFileRead = 0; |
| 948 | void *zUnicodePath; |
| 949 | char *zUtf8Name; |
| 950 | static int recursionLevel = 0; /* Bookkeeping about the recursion level */ |
| 951 | static char *zFnRid1 = 0; /* The file holding the artifact with RID=1 */ |
| 952 | static int cchPathInitial = 0; /* The length of zPath on first recursion */ |
| 953 | |
| 954 | recursionLevel++; |
| 955 | if( recursionLevel==1 ){ |
| 956 | cchPathInitial = strlen(zPath); |
| 957 | if( fKeepRid1!=0 ){ |
| 958 | char *zFnDotRid1 = mprintf("%s/.rid1", zPath); |
| 959 | Blob bFileContents; |
| 960 | if( blob_read_from_file(&bFileContents, zFnDotRid1, ExtFILE)!=-1 ){ |
| 961 | Blob line, value; |
| 962 | while( blob_line(&bFileContents, &line)>0 ){ |
| 963 | if( blob_token(&line, &value)==0 ) continue; /* Empty line */ |
| 964 | if( blob_buffer(&value)[0]=='#' ) continue; /* Comment */ |
| 965 | blob_trim(&value); |
| 966 | zFnRid1 = mprintf("%s/%s", zPath, blob_str(&value)); |
| 967 | break; |
| 968 | } |
| 969 | blob_reset(&bFileContents); |
| 970 | if( zFnRid1 ){ |
| 971 | if( blob_read_from_file(&aContent, zFnRid1, ExtFILE)==-1 ){ |
| 972 | fossil_fatal("some unknown error occurred while reading \"%s\"", |
| 973 | zFnRid1); |
| 974 | }else{ |
| 975 | recon_set_hash_policy(0, zFnRid1); |
| 976 | content_put(&aContent); |
| 977 | recon_restore_hash_policy(); |
| 978 | blob_reset(&aContent); |
| 979 | fossil_print("\r%d", ++nFileRead); |
| 980 | fflush(stdout); |
| 981 | } |
| 982 | }else{ |
| 983 | fossil_fatal("an error occurred while reading or parsing \"%s\"", |
| 984 | zFnDotRid1); |
| 985 | } |
| 986 | } |
| 987 | free(zFnDotRid1); |
| 988 | } |
| 989 | } |
| 990 | zUnicodePath = fossil_utf8_to_path(zPath, 1); |
| 991 | d = opendir(zUnicodePath); |
| 992 | if( d ){ |
| 993 | while( (pEntry=readdir(d))!=0 ){ |
| 994 | Blob path; |
| @@ -953,18 +1006,20 @@ | |
| 1006 | #else |
| 1007 | if( file_isdir(zSubpath, ExtFILE)==1 ) |
| 1008 | #endif |
| 1009 | { |
| 1010 | recon_read_dir(zSubpath); |
| 1011 | }else if( fossil_strcmp(zSubpath, zFnRid1)!=0 ){ |
| 1012 | blob_init(&path, 0, 0); |
| 1013 | blob_appendf(&path, "%s", zSubpath); |
| 1014 | if( blob_read_from_file(&aContent, blob_str(&path), ExtFILE)==-1 ){ |
| 1015 | fossil_fatal("some unknown error occurred while reading \"%s\"", |
| 1016 | blob_str(&path)); |
| 1017 | } |
| 1018 | recon_set_hash_policy(cchPathInitial, blob_str(&path)); |
| 1019 | content_put(&aContent); |
| 1020 | recon_restore_hash_policy(); |
| 1021 | blob_reset(&path); |
| 1022 | blob_reset(&aContent); |
| 1023 | fossil_print("\r%d", ++nFileRead); |
| 1024 | fflush(stdout); |
| 1025 | } |
| @@ -974,10 +1029,49 @@ | |
| 1029 | }else { |
| 1030 | fossil_fatal("encountered error %d while trying to open \"%s\".", |
| 1031 | errno, g.argv[3]); |
| 1032 | } |
| 1033 | fossil_path_free(zUnicodePath); |
| 1034 | if( recursionLevel==1 && zFnRid1!=0 ) free(zFnRid1); |
| 1035 | recursionLevel--; |
| 1036 | } |
| 1037 | |
| 1038 | /* |
| 1039 | ** Helper functions called from recon_read_dir() to set and restore the correct |
| 1040 | ** hash policy for an artifact read from disk, inferred from the length of the |
| 1041 | ** path name. |
| 1042 | */ |
| 1043 | #define HPOLICY_NOTDEFINED -1 |
| 1044 | static int saved_eHashPolicy = HPOLICY_NOTDEFINED; |
| 1045 | |
| 1046 | void recon_set_hash_policy( |
| 1047 | const int cchPathPrefix, /* Directory prefix length for zUuidAsFilePath */ |
| 1048 | const char *zUuidAsFilePath /* Relative, well-formed, from recon_read_dir() */ |
| 1049 | ){ |
| 1050 | int cchTotal, cchHashPart; |
| 1051 | int new_eHashPolicy = HPOLICY_NOTDEFINED; |
| 1052 | assert( HNAME_COUNT==2 ); /* Review function if new hashes are implemented. */ |
| 1053 | if( zUuidAsFilePath==0 ) return; |
| 1054 | cchTotal = strlen(zUuidAsFilePath); |
| 1055 | if( cchTotal==0 ) return; |
| 1056 | if( cchPathPrefix>=cchTotal) return; |
| 1057 | cchHashPart = cchTotal - cchPathPrefix; |
| 1058 | if( cchHashPart>=HNAME_LEN_K256 ){ |
| 1059 | new_eHashPolicy = HPOLICY_SHA3; |
| 1060 | }else if( cchHashPart>=HNAME_LEN_SHA1 ){ |
| 1061 | new_eHashPolicy = HPOLICY_SHA1; |
| 1062 | } |
| 1063 | if( new_eHashPolicy!=HPOLICY_NOTDEFINED ){ |
| 1064 | saved_eHashPolicy = g.eHashPolicy; |
| 1065 | g.eHashPolicy = new_eHashPolicy; |
| 1066 | } |
| 1067 | } |
| 1068 | |
| 1069 | void recon_restore_hash_policy(){ |
| 1070 | if( saved_eHashPolicy!=HPOLICY_NOTDEFINED ){ |
| 1071 | g.eHashPolicy = saved_eHashPolicy; |
| 1072 | } |
| 1073 | } |
| 1074 | |
| 1075 | /* |
| 1076 | ** COMMAND: reconstruct* |
| 1077 | ** |
| @@ -1049,11 +1143,10 @@ | |
| 1143 | ** --private Include private artifacts. |
| 1144 | ** |
| 1145 | ** See also: rebuild, reconstruct |
| 1146 | */ |
| 1147 | void deconstruct_cmd(void){ |
| 1148 | const char *zPrefixOpt; |
| 1149 | Stmt s; |
| 1150 | int privateFlag; |
| 1151 | |
| 1152 | /* get and check prefix length argument and build format string */ |
| @@ -1092,10 +1185,11 @@ | |
| 1185 | if( prefixLength ){ |
| 1186 | zFNameFormat = mprintf("%s/%%.%ds/%%s",zDestDir,prefixLength); |
| 1187 | }else{ |
| 1188 | zFNameFormat = mprintf("%s/%%s",zDestDir); |
| 1189 | } |
| 1190 | cchFNamePrefix = strlen(zDestDir); |
| 1191 | |
| 1192 | bag_init(&bagDone); |
| 1193 | ttyOutput = 1; |
| 1194 | processCnt = 0; |
| 1195 | if (!g.fQuiet) { |
| 1196 |