dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Copyright (c) 2007 D. Richard Hipp dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is free software; you can redistribute it and/or dbda8d6ce9 2007-07-21 drh: ** modify it under the terms of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License version 2 as published by the Free Software Foundation. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is distributed in the hope that it will be useful, dbda8d6ce9 2007-07-21 drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of dbda8d6ce9 2007-07-21 drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dbda8d6ce9 2007-07-21 drh: ** General Public License for more details. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** You should have received a copy of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License along with this library; if not, write to the dbda8d6ce9 2007-07-21 drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, dbda8d6ce9 2007-07-21 drh: ** Boston, MA 02111-1307, USA. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Author contact information: dbda8d6ce9 2007-07-21 drh: ** drh@hwaci.com dbda8d6ce9 2007-07-21 drh: ** http://www.hwaci.com/drh/ dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ******************************************************************************* dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Procedures for managing the VFILE table. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #include "config.h" dbda8d6ce9 2007-07-21 drh: #include "vfile.h" dbda8d6ce9 2007-07-21 drh: #include <assert.h> dbda8d6ce9 2007-07-21 drh: #include <sys/types.h> dbda8d6ce9 2007-07-21 drh: #include <dirent.h> dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Given a UUID, return the corresponding record ID. If the UUID dbda8d6ce9 2007-07-21 drh: ** does not exist, then return 0. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** For this routine, the UUID must be exact. For a match against dbda8d6ce9 2007-07-21 drh: ** user input with mixed case, use resolve_uuid(). dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** If the UUID is not found and phantomize is 1, then attempt to dbda8d6ce9 2007-07-21 drh: ** create a phantom record. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: int uuid_to_rid(const char *zUuid, int phantomize){ dbda8d6ce9 2007-07-21 drh: int rid, sz; 043d63d4aa 2008-03-08 drh: static Stmt q; 6eca3132fe 2007-08-09 drh: char z[UUID_SIZE+1]; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: sz = strlen(zUuid); dbda8d6ce9 2007-07-21 drh: if( sz!=UUID_SIZE || !validate16(zUuid, sz) ){ dbda8d6ce9 2007-07-21 drh: return 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: strcpy(z, zUuid); dbda8d6ce9 2007-07-21 drh: canonical16(z, sz); 043d63d4aa 2008-03-08 drh: db_static_prepare(&q, "SELECT rid FROM blob WHERE uuid=:uuid"); 043d63d4aa 2008-03-08 drh: db_bind_text(&q, ":uuid", z); 043d63d4aa 2008-03-08 drh: if( db_step(&q)==SQLITE_ROW ){ 043d63d4aa 2008-03-08 drh: rid = db_column_int(&q, 0); 043d63d4aa 2008-03-08 drh: }else{ 043d63d4aa 2008-03-08 drh: rid = 0; 043d63d4aa 2008-03-08 drh: } 043d63d4aa 2008-03-08 drh: db_reset(&q); dbda8d6ce9 2007-07-21 drh: if( rid==0 && phantomize ){ 043d63d4aa 2008-03-08 drh: rid = content_new(zUuid); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: return rid; 8c828207a2 2007-08-27 drh: } 8c828207a2 2007-08-27 drh: 8c828207a2 2007-08-27 drh: /* 8c828207a2 2007-08-27 drh: ** Verify that an object is not a phantom. If the object is 8c828207a2 2007-08-27 drh: ** a phantom, output an error message and quick. 8c828207a2 2007-08-27 drh: */ 8c828207a2 2007-08-27 drh: void vfile_verify_not_phantom(int rid, const char *zFilename){ 8c828207a2 2007-08-27 drh: if( db_int(-1, "SELECT size FROM blob WHERE rid=%d", rid)<0 ){ 8c828207a2 2007-08-27 drh: if( zFilename ){ 8c828207a2 2007-08-27 drh: fossil_fatal("content missing for %s", zFilename); 8c828207a2 2007-08-27 drh: }else{ 8c828207a2 2007-08-27 drh: char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); 8c828207a2 2007-08-27 drh: if( zUuid ){ 8c828207a2 2007-08-27 drh: fossil_fatal("content missing for [%.10s]", zUuid); 8c828207a2 2007-08-27 drh: }else{ 8c828207a2 2007-08-27 drh: fossil_panic("bad object id: %d", rid); 8c828207a2 2007-08-27 drh: } 8c828207a2 2007-08-27 drh: } 8c828207a2 2007-08-27 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Build a catalog of all files in a baseline. dbda8d6ce9 2007-07-21 drh: ** We scan the baseline file for lines of the form: dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** F NAME UUID dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Each such line makes an entry in the VFILE table. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void vfile_build(int vid, Blob *p){ dbda8d6ce9 2007-07-21 drh: int rid; dbda8d6ce9 2007-07-21 drh: char *zName, *zUuid; dbda8d6ce9 2007-07-21 drh: Stmt ins; dbda8d6ce9 2007-07-21 drh: Blob line, token, name, uuid; dbda8d6ce9 2007-07-21 drh: int seenHeader = 0; dbda8d6ce9 2007-07-21 drh: db_begin_transaction(); 8c828207a2 2007-08-27 drh: vfile_verify_not_phantom(vid, 0); dbda8d6ce9 2007-07-21 drh: db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid); dbda8d6ce9 2007-07-21 drh: db_prepare(&ins, dbda8d6ce9 2007-07-21 drh: "INSERT INTO vfile(vid,rid,mrid,pathname) " dbda8d6ce9 2007-07-21 drh: " VALUES(:vid,:id,:id,:name)"); dbda8d6ce9 2007-07-21 drh: db_bind_int(&ins, ":vid", vid); dbda8d6ce9 2007-07-21 drh: while( blob_line(p, &line) ){ dbda8d6ce9 2007-07-21 drh: char *z = blob_buffer(&line); dbda8d6ce9 2007-07-21 drh: if( z[0]=='-' ){ dbda8d6ce9 2007-07-21 drh: if( seenHeader ) break; 3ed9214338 2007-09-22 drh: while( blob_line(p, &line)>2 ){} dbda8d6ce9 2007-07-21 drh: if( blob_line(p, &line)==0 ) break; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: seenHeader = 1; dbda8d6ce9 2007-07-21 drh: if( z[0]!='F' || z[1]!=' ' ) continue; dbda8d6ce9 2007-07-21 drh: blob_token(&line, &token); /* Skip the "F" token */ dbda8d6ce9 2007-07-21 drh: if( blob_token(&line, &name)==0 ) break; dbda8d6ce9 2007-07-21 drh: if( blob_token(&line, &uuid)==0 ) break; dbda8d6ce9 2007-07-21 drh: zName = blob_str(&name); dbda8d6ce9 2007-07-21 drh: defossilize(zName); dbda8d6ce9 2007-07-21 drh: zUuid = blob_str(&uuid); dbda8d6ce9 2007-07-21 drh: rid = uuid_to_rid(zUuid, 0); 8c828207a2 2007-08-27 drh: vfile_verify_not_phantom(rid, zName); dbda8d6ce9 2007-07-21 drh: if( rid>0 && file_is_simple_pathname(zName) ){ dbda8d6ce9 2007-07-21 drh: db_bind_int(&ins, ":id", rid); dbda8d6ce9 2007-07-21 drh: db_bind_text(&ins, ":name", zName); dbda8d6ce9 2007-07-21 drh: db_step(&ins); dbda8d6ce9 2007-07-21 drh: db_reset(&ins); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: blob_reset(&name); dbda8d6ce9 2007-07-21 drh: blob_reset(&uuid); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&ins); dbda8d6ce9 2007-07-21 drh: db_end_transaction(0); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Check the file signature of the disk image for every VFILE of vid. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Set the VFILE.CHNGED field on every file that has changed. Also dbda8d6ce9 2007-07-21 drh: ** set VFILE.CHNGED on every folder that contains a file or folder dbda8d6ce9 2007-07-21 drh: ** that has changed. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** If VFILE.DELETED is null or if VFILE.RID is zero, then we can assume dbda8d6ce9 2007-07-21 drh: ** the file has changed without having the check the on-disk image. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void vfile_check_signature(int vid){ dbda8d6ce9 2007-07-21 drh: Stmt q; dbda8d6ce9 2007-07-21 drh: Blob fileCksum, origCksum; 2dffce041d 2008-12-06 drh: int checkMtime = db_get_boolean("mtime-changes", 0); dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: db_begin_transaction(); dbda8d6ce9 2007-07-21 drh: db_prepare(&q, "SELECT id, %Q || pathname," 2dffce041d 2008-12-06 drh: " vfile.mrid, deleted, chnged, uuid, mtime" dbda8d6ce9 2007-07-21 drh: " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid" dbda8d6ce9 2007-07-21 drh: " WHERE vid=%d ", g.zLocalRoot, vid); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: int id, rid, isDeleted; dbda8d6ce9 2007-07-21 drh: const char *zName; dbda8d6ce9 2007-07-21 drh: int chnged = 0; dbda8d6ce9 2007-07-21 drh: int oldChnged; 2dffce041d 2008-12-06 drh: i64 oldMtime; 2dffce041d 2008-12-06 drh: i64 currentMtime; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: id = db_column_int(&q, 0); dbda8d6ce9 2007-07-21 drh: zName = db_column_text(&q, 1); dbda8d6ce9 2007-07-21 drh: rid = db_column_int(&q, 2); dbda8d6ce9 2007-07-21 drh: isDeleted = db_column_int(&q, 3); dbda8d6ce9 2007-07-21 drh: oldChnged = db_column_int(&q, 4); 2dffce041d 2008-12-06 drh: oldMtime = db_column_int64(&q, 6); dbda8d6ce9 2007-07-21 drh: if( oldChnged>=2 ){ dbda8d6ce9 2007-07-21 drh: chnged = oldChnged; dbda8d6ce9 2007-07-21 drh: }else if( isDeleted || rid==0 ){ dbda8d6ce9 2007-07-21 drh: chnged = 1; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( chnged!=1 ){ 2dffce041d 2008-12-06 drh: currentMtime = file_mtime(zName); 2dffce041d 2008-12-06 drh: } 2dffce041d 2008-12-06 drh: if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){ dbda8d6ce9 2007-07-21 drh: db_ephemeral_blob(&q, 5, &origCksum); dbda8d6ce9 2007-07-21 drh: if( sha1sum_file(zName, &fileCksum) ){ dbda8d6ce9 2007-07-21 drh: blob_zero(&fileCksum); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( blob_compare(&fileCksum, &origCksum) ){ dbda8d6ce9 2007-07-21 drh: chnged = 1; 2dffce041d 2008-12-06 drh: }else if( currentMtime!=oldMtime ){ 2dffce041d 2008-12-06 drh: db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", 2dffce041d 2008-12-06 drh: currentMtime, id); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: blob_reset(&origCksum); dbda8d6ce9 2007-07-21 drh: blob_reset(&fileCksum); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( chnged!=oldChnged ){ dbda8d6ce9 2007-07-21 drh: db_multi_exec("UPDATE vfile SET chnged=%d WHERE id=%d", chnged, id); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: db_end_transaction(0); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Write all files from vid to the disk. Or if vid==0 and id!=0 dbda8d6ce9 2007-07-21 drh: ** write just the specific file where VFILE.ID=id. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void vfile_to_disk(int vid, int id, int verbose){ dbda8d6ce9 2007-07-21 drh: Stmt q; dbda8d6ce9 2007-07-21 drh: Blob content; dbda8d6ce9 2007-07-21 drh: int nRepos = strlen(g.zLocalRoot); dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: if( vid>0 && id==0 ){ dbda8d6ce9 2007-07-21 drh: db_prepare(&q, "SELECT id, %Q || pathname, mrid" dbda8d6ce9 2007-07-21 drh: " FROM vfile" dbda8d6ce9 2007-07-21 drh: " WHERE vid=%d AND mrid>0", dbda8d6ce9 2007-07-21 drh: g.zLocalRoot, vid); dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: assert( vid==0 && id>0 ); dbda8d6ce9 2007-07-21 drh: db_prepare(&q, "SELECT id, %Q || pathname, mrid" dbda8d6ce9 2007-07-21 drh: " FROM vfile" dbda8d6ce9 2007-07-21 drh: " WHERE id=%d AND mrid>0", dbda8d6ce9 2007-07-21 drh: g.zLocalRoot, id); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: int id, rid; dbda8d6ce9 2007-07-21 drh: const char *zName; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: id = db_column_int(&q, 0); dbda8d6ce9 2007-07-21 drh: zName = db_column_text(&q, 1); dbda8d6ce9 2007-07-21 drh: rid = db_column_int(&q, 2); dbda8d6ce9 2007-07-21 drh: content_get(rid, &content); dbda8d6ce9 2007-07-21 drh: if( verbose ) printf("%s\n", &zName[nRepos]); dbda8d6ce9 2007-07-21 drh: blob_write_to_file(&content, zName); 2dffce041d 2008-12-06 drh: db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", 2dffce041d 2008-12-06 drh: file_mtime(zName), id); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Delete from the disk every file in VFILE vid. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void vfile_unlink(int vid){ dbda8d6ce9 2007-07-21 drh: Stmt q; dbda8d6ce9 2007-07-21 drh: db_prepare(&q, "SELECT %Q || pathname FROM vfile" dbda8d6ce9 2007-07-21 drh: " WHERE vid=%d AND mrid>0", g.zLocalRoot, vid); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: const char *zName; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: zName = db_column_text(&q, 0); dbda8d6ce9 2007-07-21 drh: unlink(zName); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&q); 2dffce041d 2008-12-06 drh: db_multi_exec("UPDATE vfile SET mtime=NULL HERE vid=%d AND mrid>0", vid); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Load into table SFILE the name of every ordinary file in 849b94c631 2008-07-17 drh: ** the directory pPath. Omit the first nPrefix characters of 849b94c631 2008-07-17 drh: ** of pPath when inserting into the SFILE table. 849b94c631 2008-07-17 drh: ** 849b94c631 2008-07-17 drh: ** Subdirectories are scanned recursively. dbda8d6ce9 2007-07-21 drh: ** Omit files named in VFILE.vid dbda8d6ce9 2007-07-21 drh: */ 849b94c631 2008-07-17 drh: void vfile_scan(int vid, Blob *pPath, int nPrefix){ dbda8d6ce9 2007-07-21 drh: DIR *d; dbda8d6ce9 2007-07-21 drh: int origSize; dbda8d6ce9 2007-07-21 drh: const char *zDir; dbda8d6ce9 2007-07-21 drh: struct dirent *pEntry; dbda8d6ce9 2007-07-21 drh: static const char *zSql = "SELECT 1 FROM vfile " 849b94c631 2008-07-17 drh: " WHERE pathname=%Q AND NOT deleted"; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: origSize = blob_size(pPath); dbda8d6ce9 2007-07-21 drh: zDir = blob_str(pPath); dbda8d6ce9 2007-07-21 drh: d = opendir(zDir); dbda8d6ce9 2007-07-21 drh: if( d ){ dbda8d6ce9 2007-07-21 drh: while( (pEntry=readdir(d))!=0 ){ dbda8d6ce9 2007-07-21 drh: char *zPath; dbda8d6ce9 2007-07-21 drh: if( pEntry->d_name[0]=='.' ) continue; 849b94c631 2008-07-17 drh: blob_appendf(pPath, "/%s", pEntry->d_name); dbda8d6ce9 2007-07-21 drh: zPath = blob_str(pPath); dbda8d6ce9 2007-07-21 drh: if( file_isdir(zPath)==1 ){ 849b94c631 2008-07-17 drh: vfile_scan(vid, pPath, nPrefix); 849b94c631 2008-07-17 drh: }else if( file_isfile(zPath) && !db_exists(zSql, &zPath[nPrefix+1]) ){ 849b94c631 2008-07-17 drh: db_multi_exec("INSERT INTO sfile VALUES(%Q)", &zPath[nPrefix+1]); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: blob_resize(pPath, origSize); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: closedir(d); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Compute an aggregate MD5 checksum over the disk image of every dbda8d6ce9 2007-07-21 drh: ** file in vid. The file names are part of the checksum. dbda8d6ce9 2007-07-21 drh: ** 22552fb803 2007-08-03 dan: ** This function operates differently if the Global.aCommitFile 22552fb803 2007-08-03 dan: ** variable is not NULL. In that case, the disk image is used for 22552fb803 2007-08-03 dan: ** each file in aCommitFile[] and the repository image (see 22552fb803 2007-08-03 dan: ** vfile_aggregate_checksum_repository() is used for all others). 5c74c300b1 2007-08-04 drh: ** Newly added files that are not contained in the repository are 5c74c300b1 2007-08-04 drh: ** omitted from the checksum if they are not in Global.aCommitFile. 22552fb803 2007-08-03 dan: ** dbda8d6ce9 2007-07-21 drh: ** Return the resulting checksum in blob pOut. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void vfile_aggregate_checksum_disk(int vid, Blob *pOut){ dbda8d6ce9 2007-07-21 drh: FILE *in; dbda8d6ce9 2007-07-21 drh: Stmt q; dbda8d6ce9 2007-07-21 drh: char zBuf[4096]; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); 22552fb803 2007-08-03 dan: db_prepare(&q, 22552fb803 2007-08-03 dan: "SELECT %Q || pathname, pathname, file_is_selected(id), rid FROM vfile" 22552fb803 2007-08-03 dan: " WHERE NOT deleted AND vid=%d" 22552fb803 2007-08-03 dan: " ORDER BY pathname", 22552fb803 2007-08-03 dan: g.zLocalRoot, vid 22552fb803 2007-08-03 dan: ); dbda8d6ce9 2007-07-21 drh: md5sum_init(); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: const char *zFullpath = db_column_text(&q, 0); dbda8d6ce9 2007-07-21 drh: const char *zName = db_column_text(&q, 1); 22552fb803 2007-08-03 dan: int isSelected = db_column_int(&q, 2); 22552fb803 2007-08-03 dan: 22552fb803 2007-08-03 dan: if( isSelected ){ 5c74c300b1 2007-08-04 drh: md5sum_step_text(zName, -1); 22552fb803 2007-08-03 dan: in = fopen(zFullpath,"rb"); 22552fb803 2007-08-03 dan: if( in==0 ){ 22552fb803 2007-08-03 dan: md5sum_step_text(" 0\n", -1); 22552fb803 2007-08-03 dan: continue; 22552fb803 2007-08-03 dan: } 22552fb803 2007-08-03 dan: fseek(in, 0L, SEEK_END); 22552fb803 2007-08-03 dan: sprintf(zBuf, " %ld\n", ftell(in)); 22552fb803 2007-08-03 dan: fseek(in, 0L, SEEK_SET); 22552fb803 2007-08-03 dan: md5sum_step_text(zBuf, -1); 22552fb803 2007-08-03 dan: for(;;){ 22552fb803 2007-08-03 dan: int n; 22552fb803 2007-08-03 dan: n = fread(zBuf, 1, sizeof(zBuf), in); 22552fb803 2007-08-03 dan: if( n<=0 ) break; 22552fb803 2007-08-03 dan: md5sum_step_text(zBuf, n); 22552fb803 2007-08-03 dan: } 22552fb803 2007-08-03 dan: fclose(in); 22552fb803 2007-08-03 dan: }else{ 22552fb803 2007-08-03 dan: int rid = db_column_int(&q, 3); 22552fb803 2007-08-03 dan: char zBuf[100]; 22552fb803 2007-08-03 dan: Blob file; 22552fb803 2007-08-03 dan: 5c74c300b1 2007-08-04 drh: if( rid>0 ){ 5c74c300b1 2007-08-04 drh: md5sum_step_text(zName, -1); 5c74c300b1 2007-08-04 drh: blob_zero(&file); 5c74c300b1 2007-08-04 drh: content_get(rid, &file); 5c74c300b1 2007-08-04 drh: sprintf(zBuf, " %d\n", blob_size(&file)); 5c74c300b1 2007-08-04 drh: md5sum_step_text(zBuf, -1); 5c74c300b1 2007-08-04 drh: md5sum_step_blob(&file); 5c74c300b1 2007-08-04 drh: blob_reset(&file); 5c74c300b1 2007-08-04 drh: } 22552fb803 2007-08-03 dan: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: md5sum_finish(pOut); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Compute an aggregate MD5 checksum over the repository image of every dbda8d6ce9 2007-07-21 drh: ** file in vid. The file names are part of the checksum. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Return the resulting checksum in blob pOut. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void vfile_aggregate_checksum_repository(int vid, Blob *pOut){ dbda8d6ce9 2007-07-21 drh: Blob file; dbda8d6ce9 2007-07-21 drh: Stmt q; dbda8d6ce9 2007-07-21 drh: char zBuf[100]; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); 5c3e87171a 2007-08-01 drh: dbda8d6ce9 2007-07-21 drh: db_prepare(&q, "SELECT pathname, rid FROM vfile" dbda8d6ce9 2007-07-21 drh: " WHERE NOT deleted AND rid>0 AND vid=%d" dbda8d6ce9 2007-07-21 drh: " ORDER BY pathname", dbda8d6ce9 2007-07-21 drh: vid); dbda8d6ce9 2007-07-21 drh: blob_zero(&file); dbda8d6ce9 2007-07-21 drh: md5sum_init(); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: const char *zName = db_column_text(&q, 0); dbda8d6ce9 2007-07-21 drh: int rid = db_column_int(&q, 1); dbda8d6ce9 2007-07-21 drh: md5sum_step_text(zName, -1); dbda8d6ce9 2007-07-21 drh: content_get(rid, &file); dbda8d6ce9 2007-07-21 drh: sprintf(zBuf, " %d\n", blob_size(&file)); dbda8d6ce9 2007-07-21 drh: md5sum_step_text(zBuf, -1); dbda8d6ce9 2007-07-21 drh: md5sum_step_blob(&file); dbda8d6ce9 2007-07-21 drh: blob_reset(&file); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: md5sum_finish(pOut); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* 5c3e87171a 2007-08-01 drh: ** Compute an aggregate MD5 checksum over the repository image of every 5c3e87171a 2007-08-01 drh: ** file in manifest vid. The file names are part of the checksum. 5c3e87171a 2007-08-01 drh: ** 5c3e87171a 2007-08-01 drh: ** Return the resulting checksum in blob pOut. 5c3e87171a 2007-08-01 drh: */ 3945057916 2007-08-01 drh: void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){ 5c3e87171a 2007-08-01 drh: int i, fid; 5c3e87171a 2007-08-01 drh: Blob file, mfile; 5c3e87171a 2007-08-01 drh: Manifest m; 5c3e87171a 2007-08-01 drh: char zBuf[100]; 5c3e87171a 2007-08-01 drh: 1871a93dd4 2007-08-30 drh: blob_zero(pOut); 1871a93dd4 2007-08-30 drh: if( pManOut ){ 1871a93dd4 2007-08-30 drh: blob_zero(pManOut); 1871a93dd4 2007-08-30 drh: } 5c3e87171a 2007-08-01 drh: db_must_be_within_tree(); 5c3e87171a 2007-08-01 drh: content_get(vid, &mfile); 5c3e87171a 2007-08-01 drh: if( manifest_parse(&m, &mfile)==0 ){ 1871a93dd4 2007-08-30 drh: fossil_panic("manifest file (%d) is malformed", vid); 5c3e87171a 2007-08-01 drh: } 5c3e87171a 2007-08-01 drh: for(i=0; i<m.nFile; i++){ 5c3e87171a 2007-08-01 drh: fid = uuid_to_rid(m.aFile[i].zUuid, 0); 5c3e87171a 2007-08-01 drh: md5sum_step_text(m.aFile[i].zName, -1); 5c3e87171a 2007-08-01 drh: content_get(fid, &file); 5c3e87171a 2007-08-01 drh: sprintf(zBuf, " %d\n", blob_size(&file)); 5c3e87171a 2007-08-01 drh: md5sum_step_text(zBuf, -1); 5c3e87171a 2007-08-01 drh: md5sum_step_blob(&file); 5c3e87171a 2007-08-01 drh: blob_reset(&file); 5c3e87171a 2007-08-01 drh: } 3945057916 2007-08-01 drh: if( pManOut ){ 3945057916 2007-08-01 drh: blob_append(pManOut, m.zRepoCksum, -1); 3945057916 2007-08-01 drh: } 5c3e87171a 2007-08-01 drh: manifest_clear(&m); 5c3e87171a 2007-08-01 drh: md5sum_finish(pOut); 5c3e87171a 2007-08-01 drh: } 5c3e87171a 2007-08-01 drh: 5c3e87171a 2007-08-01 drh: /* dbda8d6ce9 2007-07-21 drh: ** COMMAND: test-agg-cksum dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void test_agg_cksum_cmd(void){ dbda8d6ce9 2007-07-21 drh: int vid; 3945057916 2007-08-01 drh: Blob hash, hash2; dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); dbda8d6ce9 2007-07-21 drh: vid = db_lget_int("checkout", 0); dbda8d6ce9 2007-07-21 drh: vfile_aggregate_checksum_disk(vid, &hash); 5c3e87171a 2007-08-01 drh: printf("disk: %s\n", blob_str(&hash)); dbda8d6ce9 2007-07-21 drh: blob_reset(&hash); dbda8d6ce9 2007-07-21 drh: vfile_aggregate_checksum_repository(vid, &hash); 5c3e87171a 2007-08-01 drh: printf("archive: %s\n", blob_str(&hash)); 5c3e87171a 2007-08-01 drh: blob_reset(&hash); 3945057916 2007-08-01 drh: vfile_aggregate_checksum_manifest(vid, &hash, &hash2); 5c3e87171a 2007-08-01 drh: printf("manifest: %s\n", blob_str(&hash)); 3945057916 2007-08-01 drh: printf("recorded: %s\n", blob_str(&hash2)); dbda8d6ce9 2007-07-21 drh: }