int Backup::Save() { if (m_is_saving) { return 1; } if (m_server->m_cfg.backup_dir.empty()) { ERROR_LOG("Empty bakup dir for backup."); return -1; } //m_server->m_db->CloseAll(); m_is_saving = true; int ret = 0; char cmd[m_server->m_cfg.data_base_path.size() + 256]; make_dir(m_server->m_cfg.backup_dir); char dest[m_server->m_cfg.backup_dir.size() + 256]; char shasumfile[m_server->m_cfg.backup_dir.size() + 256]; uint32 now = time(NULL); sprintf(dest, "%s/dbsave-%u.tar", m_server->m_cfg.backup_dir.c_str(), now); sprintf(shasumfile, "%s/dbsave-%u.sha", m_server->m_cfg.backup_dir.c_str(), now); std::string source = m_server->m_cfg.data_base_path; if (0 == chdir(m_server->m_cfg.data_base_path.c_str())) { source = "*"; } sprintf(cmd, "tar cf %s %s;", dest, source.c_str()); ret = system(cmd); if (0 != chdir(m_server->m_cfg.home.c_str())) { WARN_LOG("Failed to change dir to home:%s", m_server->m_cfg.home.c_str()); } if (-1 == ret) { ERROR_LOG( "Failed to create backup data archive:%s", dest); } else { std::string sha1sum_str; ret = sha1sum_file(dest, sha1sum_str); if (-1 == ret) { ERROR_LOG( "Failed to compute sha1sum for data archive:%s", dest); } else { INFO_LOG("Save file SHA1sum is %s", sha1sum_str.c_str()); file_write_content(shasumfile, sha1sum_str); m_last_save = now; } } m_is_saving = false; return ret; }
/* ** Look at every VFILE entry with the given vid and set update ** VFILE.CHNGED field on every file according to whether or not ** the file has changes. 0 means no change. 1 means edited. 2 means ** the file has changed due to a merge. 3 means the file was added ** by a merge. ** ** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was ** either removed from managemented via "vcs rm" or added via ** "vcs add", respectively, and in both cases we always know that ** the file has changed without having the check the size, mtime, ** or on-disk content. ** ** If the size of the file has changed, then we always know that the file ** changed without having to look at the mtime or on-disk content. ** ** The mtime of the file is only a factor if the mtime-changes setting ** is false and the useSha1sum flag is false. If the mtime-changes ** setting is true (or undefined - it defaults to true) or if useSha1sum ** is true, then we do not trust the mtime and will examine the on-disk ** content to determine if a file really is the same. ** ** If the mtime is used, it is used only to determine if files are the same. ** If the mtime of a file has changed, we still examine the on-disk content ** to see whether or not the edit was a null-edit. */ void vfile_check_signature(int vid, int notFileIsFatal, int useSha1sum){ int nErr = 0; Stmt q; Blob fileCksum, origCksum; int useMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1); db_begin_transaction(); db_prepare(&q, "SELECT id, %Q || pathname," " vfile.mrid, deleted, chnged, uuid, size, mtime" " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid" " WHERE vid=%d ", g.zLocalRoot, vid); while( db_step(&q)==SQLITE_ROW ){ int id, rid, isDeleted; const char *zName; int chnged = 0; int oldChnged; i64 oldMtime; i64 currentMtime; i64 origSize; i64 currentSize; id = db_column_int(&q, 0); zName = db_column_text(&q, 1); rid = db_column_int(&q, 2); isDeleted = db_column_int(&q, 3); oldChnged = chnged = db_column_int(&q, 4); oldMtime = db_column_int64(&q, 7); currentSize = file_wd_size(zName); origSize = db_column_int64(&q, 6); currentMtime = file_wd_mtime(0); if( chnged==0 && (isDeleted || rid==0) ){ /* "vcs rm" or "vcs add" always change the file */ chnged = 1; }else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){ if( notFileIsFatal ){ vcs_warning("not an ordinary file: %s", zName); nErr++; } chnged = 1; } if( origSize!=currentSize ){ if( chnged!=1 ){ /* A file size change is definitive - the file has changed. No ** need to check the mtime or sha1sum */ chnged = 1; } }else if( chnged==1 && rid!=0 && !isDeleted ){ /* File is believed to have changed but it is the same size. ** Double check that it really has changed by looking at content. */ assert( origSize==currentSize ); db_ephemeral_blob(&q, 5, &origCksum); if( sha1sum_file(zName, &fileCksum) ){ blob_zero(&fileCksum); } if( blob_compare(&fileCksum, &origCksum)==0 ) chnged = 0; blob_reset(&origCksum); blob_reset(&fileCksum); }else if( chnged==0 && (useMtime==0 || currentMtime!=oldMtime) ){ /* For files that were formerly believed to be unchanged, if their ** mtime changes, or unconditionally if --sha1sum is used, check ** to see if they have been edited by looking at their SHA1 sum */ assert( origSize==currentSize ); db_ephemeral_blob(&q, 5, &origCksum); if( sha1sum_file(zName, &fileCksum) ){ blob_zero(&fileCksum); } if( blob_compare(&fileCksum, &origCksum) ){ chnged = 1; } blob_reset(&origCksum); blob_reset(&fileCksum); } if( currentMtime!=oldMtime || chnged!=oldChnged ){ db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d", currentMtime, chnged, id); } } db_finalize(&q); if( nErr ) vcs_fatal("abort due to prior errors"); db_end_transaction(0); }