File Annotation
Not logged in
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;
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,"
dbda8d6ce9 2007-07-21       drh:                  "       vfile.mrid, deleted, chnged, uuid"
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;
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);
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 ){
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;
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);
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);
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
dbda8d6ce9 2007-07-21       drh: ** the directory pPath.  Subdirectories are scanned recursively.
dbda8d6ce9 2007-07-21       drh: ** Omit files named in VFILE.vid
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void vfile_scan(int vid, Blob *pPath){
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:   const char *zFormat;
dbda8d6ce9 2007-07-21       drh:   struct dirent *pEntry;
dbda8d6ce9 2007-07-21       drh:   static const char *zSql = "SELECT 1 FROM vfile "
dbda8d6ce9 2007-07-21       drh:                             " WHERE pathname=%B 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:   if( zDir[0]==0 ){
dbda8d6ce9 2007-07-21       drh:      zDir = ".";
dbda8d6ce9 2007-07-21       drh:      zFormat = "%s";
dbda8d6ce9 2007-07-21       drh:   }else{
dbda8d6ce9 2007-07-21       drh:      zFormat = "/%s";
dbda8d6ce9 2007-07-21       drh:   }
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;
dbda8d6ce9 2007-07-21       drh:       blob_appendf(pPath, zFormat, pEntry->d_name);
dbda8d6ce9 2007-07-21       drh:       zPath = blob_str(pPath);
dbda8d6ce9 2007-07-21       drh:       if( file_isdir(zPath)==1 ){
dbda8d6ce9 2007-07-21       drh:         vfile_scan(vid, pPath);
dbda8d6ce9 2007-07-21       drh:       }else if( file_isfile(zPath) && !db_exists(zSql,pPath) ){
dbda8d6ce9 2007-07-21       drh:         db_multi_exec("INSERT INTO sfile VALUES(%B)", pPath);
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: }