static rc_t CopierMakeF (Copier * cp, KDirectory * dir, const char * path) { rc_t rc, orc; KFile * fm; rc = KDirectoryCreateFile (dir, &fm, true, 0666, kcmCreate|kcmParents, "%s.md5", path); if (rc == 0) { KMD5SumFmt * md5f; rc = KMD5SumFmtMakeUpdate (&md5f, fm); if (rc == 0) { KFile * f; rc = KDirectoryCreateFile (dir, &f, false, 0666, kcmCreate, "%s", path); if (rc == 0) { KMD5File * fmd5; rc = KMD5FileMakeWrite (&fmd5, f, md5f, path); if (rc == 0) { cp->f = KMD5FileToKFile (fmd5); orc = KMD5SumFmtRelease (md5f); if (orc) LOGERR (klogInt, orc, "Failure releasing MD5 format"); cp->o = 0; /* start of file */ return rc; } orc = KFileRelease (f); if (orc) LOGERR (klogInt, orc, "Failure releasing Copier file"); } orc = KMD5SumFmtRelease (md5f); if (orc) LOGERR (klogInt, orc, "Failure releasing MD5 format"); } orc = KFileRelease (fm); if (orc) LOGERR (klogInt, orc, "Failure releasing MD5SUM file"); } return rc; }
rc_t KU64IndexPersist_v3(KU64Index_v3* self, bool proj, KDirectory *dir, const char *path, bool use_md5) { KU64Index_PersistData pd; char tmpname[256]; char tmpmd5name[256]; char md5path[256]; self->rc = 0; memset(&pd, 0, sizeof(KU64Index_PersistData)); self->rc = KDirectoryResolvePath(dir, false, tmpname, sizeof(tmpname), "%s.tmp", path); if( self->rc == 0 ) { self->rc = KDirectoryCreateFile(dir, &pd.file, true, 0664, kcmInit, "%s", tmpname); if(use_md5 && self->rc == 0 ) { KMD5SumFmt *km = NULL; size_t tmplen = snprintf(tmpmd5name, sizeof(tmpmd5name), "%s.md5", tmpname); KFile* kf = NULL; if( tmplen >= sizeof(tmpmd5name) ) { self->rc = RC(rcDB, rcIndex, rcPersisting, rcName, rcExcessive); } else { tmplen = snprintf(md5path, sizeof(md5path), "%s.md5", path); if( tmplen >= sizeof(md5path) ) { self->rc = RC(rcDB, rcIndex, rcPersisting, rcName, rcExcessive); } else { self->rc = KDirectoryCreateFile(dir, &kf, true, 0664, kcmInit, "%s", tmpmd5name); if( self->rc == 0 ) { self->rc = KMD5SumFmtMakeUpdate(&km, kf); if( self->rc == 0 ) { KMD5File * k5f; kf = NULL; self->rc = KMD5FileMakeWrite(&k5f, pd.file, km, path); if( self->rc == 0 ) { pd.file_md5 = k5f; pd.file = KMD5FileToKFile(k5f); } /* release pass or fail */ KMD5SumFmtRelease(km); } else { KFileRelease ( kf ); } } else { KFileRelease ( kf ); } } } if( self->rc != 0 ) { KFileRelease(pd.file); } } if( self->rc == 0 ) { struct KIndexFileHeader_v3 head; size_t writ = 0; KDBHdrInit(&head.h, 3); head.index_type = kitU64; self->rc = KFileWrite(pd.file, pd.pos, &head, sizeof(struct KIndexFileHeader_v3), &writ); if( self->rc == 0 ) { pd.pos += writ; if( use_md5 ) { KMD5FileBeginTransaction(pd.file_md5); } self->rc = BSTreePersist(&self->tree, NULL, KU64Index_WriteFunc, &pd, KU64Index_AuxFunc, &pd); } KFileRelease(pd.file); pd.file = NULL; } } if( self->rc == 0 ) { self->rc = KDirectoryRename(dir, false, tmpname, path); if( self->rc == 0 ) { if ( use_md5 ) { self->rc = KDirectoryRename(dir, false, tmpmd5name, md5path); } if( self->rc == 0 ) { /* done */ return 0; } } } /* whack temporary file */ KDirectoryRemove(dir, false, "%s", tmpname); if( use_md5 ) { KDirectoryRemove(dir, false, "%s", tmpmd5name); } return self->rc; }
rc_t CopyFileToFile( const KDirectory *top, const char *inname, KDirectory *targettop, const char *outname ) { const KFile *in = NULL; KFile *out = NULL; KFile *md5file = NULL; KMD5File *md5out = NULL; KMD5SumFmt *md5sumfmt = NULL; char md5filename[1024]; rc_t rc = 0; uint32_t mode = 0; uint32_t pathtype = 0; uint32_t failed = 0; if (PathIsMD5File(top, inname)) { /* Skip it */ return 0; } rc = KDirectoryOpenFileRead( top, &in, "%s", inname ); if (rc != 0) { failed = rc; goto FAIL; } mode = DEFAULTMODE; rc = KDirectoryAccess( top, &mode, inname); if (rc != 0) { failed = rc; goto FAIL; } /* * Not sure here -- does kcmInit re-initialize the file mode as we specify? * Or does it preserve the existing mode (and do we want it to)? */ if (clobber_protections) { pathtype = KDirectoryPathType( targettop, "%s", outname ); if ((pathtype & ~kptAlias) == kptFile) { rc = KDirectorySetAccess( targettop, false, mode, 0777, "%s", outname); if (rc != 0) { failed = rc; goto FAIL; } } } rc = KDirectoryCreateFile( targettop, &out, false, mode, (force? kcmInit: kcmCreate), "%s", outname ); if (rc != 0) { failed = rc; goto FAIL; } sprintf(md5filename, "%s.md5", outname); rc = KDirectoryCreateFile( targettop, &md5file, false, DEFAULTMODE, (force? kcmInit: kcmCreate), "%s", md5filename); if (rc != 0) { failed = rc; goto FAIL; } rc = KMD5SumFmtMakeUpdate( &md5sumfmt, md5file); if (rc != 0) { failed = rc; goto FAIL; } rc = KMD5FileMakeWrite( &md5out, out, md5sumfmt, outname ); if (rc != 0) { failed = rc; goto FAIL; } { uint64_t rpos = 0; uint64_t wpos = 0; size_t numread; while (true) { rc = KFileRead( in, rpos, buffer, BUFSIZE, &numread ); /* fprintf(stderr, "Read %d bytes.\n", numread); */ if (rc == 0 && numread == 0) break; if (rc != 0) { failed = rc; goto FAIL; } rpos += numread; { size_t numwritten = 0; int written = 0; while (written < numread) { rc = KFileWrite( (KFile *)md5out, wpos, buffer+written, numread-written, &numwritten ); if (rc != 0) { failed = rc; break; } if (numwritten == 0) { fprintf(stderr, "Didn't write anything.\n"); failed = -1; goto FAIL; } wpos += numwritten; written += numwritten; } } } } /* Success also, check the value of failed to see if failed */ FAIL: if (NULL != md5out) { KFileRelease((KFile *)md5out); md5out = NULL; } /*KFileRelease(out); */ if (NULL != md5sumfmt) { KMD5SumFmtRelease(md5sumfmt); md5sumfmt = NULL; } /* KFileRelease(md5file); */ if (NULL != in) { KFileRelease(in); in = NULL; } /* KDirectoryRelease(top); */ if (failed) { KDirectoryRemove( targettop, false, "%s", md5filename ); KDirectoryRemove( targettop, false, "%s", outname); } return failed; }
static rc_t CCCopyDoFile (CCCopy * self) { const KFile * original; rc_t rc = 0; enum KCreateMode mode; PLOGMSG (klogDebug9, "CCCopyDoFile $(f)", PLOG_S(f), self->path); if (! self->force) { /* if not forced replace mode we fail on existing file */ mode = kcmCreate; } else { uint32_t tt; tt = KDirectoryPathType (self->out, self->path); switch (tt) { default: PLOGMSG (klogWarn, "File exists and will be replaced in output directory $(f)", PLOG_S(f), self->path); break; /* if the path to the file or the file do not exist no warning */ case kptNotFound: case kptBadPath: break; } tt = KDirectoryPathType (self->xml, self->path); switch (tt) { default: PLOGMSG (klogWarn, "File exists and might be replaced in xml directory $(f)", PLOG_S(f), self->path); break; /* if the path to the file or the file do not exist no warning */ case kptNotFound: case kptBadPath: break; } /* forced mode we create with init instead of create forcing a delete/create effect */ mode = kcmInit; } /* open original source for read */ rc = KDirectoryVOpenFileRead (self->in, &original, self->path, NULL); if (rc == 0) { KFile * copy; /* create copy output for write */ rc = KDirectoryVCreateFile (self->out, ©, false, 0644, mode|kcmParents, self->path, NULL); if (rc == 0) { KFile * fm; /* create parallel <path>.md5 */ rc = KDirectoryCreateFile (self->out, &fm, true, 0644, mode, "%s.md5", self->path); if (rc == 0) { KMD5SumFmt * md5f; /* make the .md5 an MD5 sum format file */ rc = KMD5SumFmtMakeUpdate (&md5f, fm); if (rc == 0) { union u { KFile * kf; KMD5File * mf; } outf; /* combine the copy and MD5 file into our special KFile */ rc = KMD5FileMakeWrite (&outf.mf, copy, md5f, self->path); if (rc == 0) { const KFile * inf; /* release this outside reference to the MD5SumFMT leaving * only the one internal to the KMD5File */ KMD5SumFmtRelease (md5f); /* create the KTeeFile that copies reads from the * original as writes to the copy. Reads will be * made by the cataloging process */ rc = KFileMakeTeeRead (&inf, original, outf.kf); if (rc == 0) { CCCat * po; KTime_t mtime; /* try to get a modification time for this pathname */ rc = KDirectoryVDate (self->in, &mtime, self->path, NULL); if (rc != 0) mtime = 0; /* default to ? 0? */ /* create the cataloger giving it the infile which * is the KTeeFile, Indirectory, the XML directory, * and the original path for the file */ rc = CCCatMake (&po, self->in, self->xml, inf, self->md5, self->ff, mtime, self->tree, false, 0, self->path); if (rc == 0) { /* do the catalog (and thus copy) */ rc = CCCatDo(po); /* release the cataloger object */ CCCatRelease (po); } else pLOGERR (klogDebug6, rc, "failure in CCCatMake $(P)", PLOG_S(P), self->path); /* release the infile which will complete a copy * regardless of the state of the cataloger */ KFileRelease (inf); /* return rc; */ } else { KFileRelease (outf.kf); KFileRelease (original); pLOGERR (klogDebug4, rc, "failure with kfilemaketeeread $(P)", PLOG_S(P), self->path); } /* rc = KFileMakeTeeRead (&inf, original, outf.kf);*/ } else { KFileRelease (copy); KMD5SumFmtRelease (md5f); pLOGERR (klogDebug4, rc, "failure with KMD5FileMakeWrite $(P)", PLOG_S(P), self->path); } /* KMD5FileMakeWrite (&outf.mf, copy, md5f, self->path); */ } /* KDirectoryCreateFile (self->out, &fm, true, 0644, mode, "%s.md5", */ else pLOGERR (klogDebug4, rc, "failure with KMD5SumFmtMakeUpdate $(P)", PLOG_S(P), self->path); KFileRelease (fm); } /* KDirectoryCreateFile (self->out, &fm, true, 0644, mode, "%s.md5", */ else pLOGERR (klogDebug4, rc, "failure with KDirectoryCreateFile $(P).md5", PLOG_S(P), self->path); KFileRelease (copy); } /* rc = KDirectoryVCreateFile (self->out, ©, false, 0644, mode|kcmParents, */ else pLOGERR (klogDebug4, rc, "failure with KDirectoryVCreateFile $(P)", PLOG_S(P), self->path); KFileRelease (original); } /* rc = KDirectoryVOpenFileRead (self->in, &original, self->path, NULL); */ else pLOGERR (klogDebug4, rc, "failure with KDirectoryVOpenFileRead $(pP)", PLOG_S(P), self->path); return rc; }