rc_t ArchiveAndEncrypt(KDirectory* wd, const char* inpath, const char* outpath, const char* passwd) { const KDirectory* d; rc_t rc = KDirectoryOpenDirRead (wd, &d, false, "%s", inpath); if (rc == 0) { const KFile* infile; rc_t rc2; rc = KDirectoryOpenTocFileRead (d, &infile, 4, NULL, NULL, NULL); if (rc == 0) { KFile* outfile; /* if the file exists, add write access */ KDirectorySetAccess( wd, false, 0600, 0777, "%s", outpath ); rc = KDirectoryCreateFile(wd, &outfile, false, 0600, kcmCreate|kcmInit, "%s", outpath); if ( rc == 0 ) { KFile* enc_outfile; KKey key; rc = KKeyInitRead(&key, kkeyAES256, passwd, string_measure(passwd, NULL)); if ( rc == 0 ) rc = KEncFileMakeWrite(&enc_outfile, outfile, &key); if (rc == 0) rc = copy_file(infile, enc_outfile); rc2 = KFileRelease(outfile); if (rc == 0) rc = rc2; /* remove write access */ rc2 = KDirectorySetAccess( wd, false, 0400, 0777, "%s", outpath ); if (rc == 0) rc = rc2; rc2 = KFileRelease(enc_outfile); if (rc == 0) rc = rc2; } rc2 = KFileRelease(infile); if (rc == 0) rc = rc2; } rc2 = KDirectoryRelease(d); if (rc == 0) rc = rc2; } return rc; }
/* * copies top/inname (a directory) * to targettop/outname, i.e. creates outname as a copy of that directory. */ rc_t CopyDirectoryToExistingDirectory( const KDirectory *top, const char *inname, KDirectory *targettop, const char *outname ) { rc_t rc; uint32_t mode; const KDirectory *source; KDirectory *dest; rc = KDirectoryOpenDirRead(top, &source, true, "%s", (const char *)inname); if (rc != 0) { LOGERR ( klogInt, rc, "can't open input directory" ); return rc; } mode = DEFAULT_DIR_MODE; rc = KDirectoryAccess( top, &mode, "%s", inname); if (rc != 0) { LOGERR ( klogInt, rc, inname ); return rc; } rc = KDirectoryCreateDir( targettop, mode, kcmOpen, "%s", outname ); if (rc != 0) { LOGERR ( klogInt, rc, "can't create output directory" ); return rc; } if (clobber_protections) { KDirectorySetAccess( targettop, false, mode, 0777, "%s", outname); } rc = KDirectoryOpenDirUpdate(targettop, &dest, true, "%s", outname); if (rc != 0) { LOGERR ( klogInt, rc, "can't open directory for write" ); return rc; } CopyDirectoryFiles(source, dest); CopyDirectoryDirectories( source, dest ); KDirectoryRelease( dest ); KDirectoryRelease( source ); return 0; }
rc_t CopyDirectoryDirectories( const KDirectory *source, KDirectory *dest ) { rc_t rc; KNamelist *list; const char *name; int i; uint32_t count; uint32_t mode; uint32_t pathtype; KDirectoryList( source, &list, PathIsDir, NULL, "."); KNamelistCount(list, &count); for (i=0; i<count; i++) { KNamelistGet(list, i, &name); /* fprintf(stderr, "Creating directory %s\n", name); */ mode = DEFAULT_DIR_MODE; rc = KDirectoryAccess( source, &mode, "%s", name); if (rc != 0) { LOGERR ( klogInt, rc, name ); return rc; } pathtype = KDirectoryPathType( dest, "%s", name ); if ((pathtype & ~kptAlias) == kptNotFound) { rc = KDirectoryCreateDir( dest, mode, kcmOpen, "%s", name ); if (rc != 0) { LOGERR ( klogInt, rc, name ); return rc; } } else if ((pathtype & ~kptAlias) == kptDir) { if (clobber_protections) { KDirectorySetAccess( dest, false, mode, 0777, "%s", name); } } CopyDirectoryToExistingDirectory( source, name, dest, (char *)name); } return 0; }
rc_t CopyMode( const KDirectory *source, const char *sourcename, KDirectory *target, char *targetname ) { /* Make sure they both exist and are the same type */ uint32_t src_pathtype; uint32_t dest_pathtype; uint32_t mode; rc_t rc; src_pathtype = KDirectoryPathType( source, "%s", sourcename ); dest_pathtype = KDirectoryPathType( target, "%s", targetname ); if ((src_pathtype & ~kptAlias) != (dest_pathtype & ~kptAlias)) { return -1; } rc = KDirectoryAccess( source, &mode, "%s", sourcename ); if (rc != 0) { LOGERR ( klogInt, rc, sourcename ); return rc; } KDirectorySetAccess( target, false, mode, 0777, "%s", targetname ); return 0; }
static rc_t FileToFile (const KDirectory * sd, const char * source, KDirectory *dd, const char * dest_, bool try_rename, char * base) { const KFile * infile; rc_t rc; uint32_t access; KTime_t date; bool is_tmp; char dest [MY_MAX_PATH + sizeof EncExt]; strcpy (dest, dest_); if (try_rename) NameFixUp (dest); if ((sd == dd) && (strcmp (source, dest) == 0)) return FileInPlace (dd, dest, try_rename); if (base == NULL) STSMSG (1, ("%scrypting file %s to %s", De, source, dest)); else STSMSG (1, ("%scrypting file %s to %s/%s", De, source, base, dest)); /* * A Hack to make stdin/stout work within KFS */ if (UseStdin) { const KFile * iinfile; rc = KFileMakeStdIn (&iinfile); if (rc == 0) { rc = KBufReadFileMakeRead (&infile, iinfile, 64 * 1024); KFileRelease (iinfile); if (rc == 0) { access = 0640; date = 0; goto stdin_shortcut; } LOGERR (klogErr, rc, "error wrapping stdin"); return rc; } } rc = 0; is_tmp = IsTmpFile (source); if (is_tmp) { TmpFoundFlag = true; if (ForceFlag) ; /* LOG OVERWRITE */ else ; /* LOG TMP */ } if (!is_tmp || ForceFlag) { rc = KDirectoryAccess (sd, &access, "%s", source); if (rc) LOGERR (klogErr, rc, "Error check permission of source"); else { rc = KDirectoryDate (sd, &date, "%s", source); if (rc) LOGERR (klogErr, rc, "Error check date of source"); else { rc = KDirectoryOpenFileRead (sd, &infile, "%s", source); if (rc) PLOGERR (klogErr, (klogErr, rc, "Error opening source file '$(S)'", "S=%s", source)); else { EncScheme scheme; stdin_shortcut: rc = EncryptionTypeCheck (infile, source, &scheme); if (rc == 0) { KFile * outfile; uint32_t kcm; /* * Hack to support stdout before VFS is complete enough to use here */ if (UseStdout) { rc = KFileMakeStdOut (&outfile); if (rc) LOGERR (klogErr, rc, "error wrapping stdout"); } else { kcm = ForceFlag ? kcmInit|kcmParents : kcmCreate|kcmParents; rc = KDirectoryCreateFile (dd, &outfile, false, 0600, kcm, "%s", dest); if (rc) PLOGERR (klogErr,(klogErr, rc, "error opening output '$(O)'", "O=%s", dest)); } if (rc == 0) { const KFile * Infile; KFile * Outfile; rc = CryptFile (infile, &Infile, outfile, &Outfile, scheme); if (rc == 0) { rc = CopyFile (Infile, Outfile, source, dest); if (rc == 0) { if (UseStdin || UseStdout) ; else { rc = KDirectorySetAccess (dd, false, access, 0777, "%s", dest); if (rc == 0 && date != 0) rc = KDirectorySetDate (dd, false, date, "%s", dest); } } KFileRelease (Infile); KFileRelease (Outfile); } KFileRelease (outfile); } } KFileRelease (infile); } } } } return rc; }
static rc_t FileInPlace (KDirectory * cwd, const char * leaf, bool try_rename) { rc_t rc; bool is_tmp; STSMSG (1, ("%scrypting file in place %s",De,leaf)); rc = 0; is_tmp = IsTmpFile (leaf); if (is_tmp) { STSMSG (1, ("%s is a vdb-decrypt/vdb-encrypt temporary file and will " "be ignored", leaf)); TmpFoundFlag = true; if (ForceFlag) ; /* LOG OVERWRITE */ else ; /* LOG TMP */ } if (!is_tmp || ForceFlag) { char temp [MY_MAX_PATH]; rc = KDirectoryResolvePath (cwd, false, temp, sizeof temp, ".%s%s", leaf, TmpExt); if (rc) PLOGERR (klogErr, (klogErr, rc, "unable to resolve '.$(S)$(E)'", "S=%s,E=%s",leaf,TmpExt)); else { KPathType kpt; uint32_t kcm; kcm = kcmCreate|kcmParents; kpt = KDirectoryPathType (cwd, temp); if (kpt != kptNotFound) { /* log busy */ if (ForceFlag) { kcm = kcmInit|kcmParents; /* log force */ kpt = kptNotFound; } } if (kpt == kptNotFound) { const KFile * infile; rc = KDirectoryOpenFileRead (cwd, &infile, "%s", leaf); if (rc) PLOGERR (klogErr, (klogErr, rc, "Unable to resolve '$(F)'", "F=%s",leaf)); else { EncScheme scheme; rc = EncryptionTypeCheck (infile, leaf, &scheme); if (rc == 0) { ArcScheme ascheme; bool changed; bool do_this_file; char new_name [MY_MAX_PATH + sizeof EncExt]; do_this_file = DoThisFile (infile, scheme, &ascheme); strcpy (new_name, leaf); if (try_rename) changed = NameFixUp (new_name); else changed = false; /* KOutMsg ("### %d \n", changed); */ if (!do_this_file) { if (changed) { STSMSG (1, ("renaming %s to %s", leaf, new_name)); rc = KDirectoryRename (cwd, false, leaf, new_name); } else STSMSG (1, ("skipping %s",leaf)); } else { KFile * outfile; rc = KDirectoryCreateExclusiveAccessFile (cwd, &outfile, false, 0600, kcm, temp); if (rc) ; else { const KFile * Infile; KFile * Outfile; rc = CryptFile (infile, &Infile, outfile, &Outfile, scheme); if (rc == 0) { STSMSG (1, ("copying %s to %s", leaf, temp)); rc = CopyFile (Infile, Outfile, leaf, temp); if (rc == 0) { uint32_t access; KTime_t date; rc = KDirectoryAccess (cwd, &access, "%s", leaf); if (rc == 0) rc = KDirectoryDate (cwd, &date, "%s", leaf); KFileRelease (infile); KFileRelease (outfile); KFileRelease (Infile); KFileRelease (Outfile); if (rc == 0) { STSMSG (1, ("renaming %s to %s", temp, new_name)); rc = KDirectoryRename (cwd, true, temp, new_name); if (rc) LOGERR (klogErr, rc, "error renaming"); else { if (changed) KDirectoryRemove (cwd, false, "%s", leaf); /*rc =*/ KDirectorySetAccess (cwd, false, access, 0777, "%s", new_name); KDirectorySetDate (cwd, false, date, "%s", new_name); /* gonna ignore an error here I think */ return rc; } } } } KFileRelease (outfile); } } } KFileRelease (infile); } } } } return 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; }