/* Make * make a memory bank * * "block_size" [ IN ] - ignored * * "limit" [ IN, DFLT ZERO ] - ignored * * "backing" [ IN ] - required. */ LIB_EXPORT rc_t CC KMemBankMake ( KMemBank **bankp, size_t block_size, uint64_t limit, KFile *backing ) { assert(backing != NULL); assert(bankp != NULL); if (bankp == NULL || backing == NULL) { PLOGMSG(klogFatal, (klogFatal, "PROGRAMMER ERROR - " __FILE__ ":$(line)", "line=%i", __LINE__)); abort(); return RC(rcFS, rcMemory, rcConstructing, rcParam, rcNull); } else { KMemBank *const self = newMemBank(); if (self == NULL) { PLOGMSG(klogFatal, (klogFatal, "OUT OF MEMORY - " __FILE__ ":$(line)", "line=%i", __LINE__)); abort(); return RC(rcFS, rcMemory, rcConstructing, rcMemory, rcExhausted); } if (backing) { self->pf = backing; KFileAddRef(self->pf); } *bankp = self; return 0; } }
/* ---------------------------------------------------------------------- * CCNodeSraDirOpenFileRead * opens an existing file with read-only access * * "f" [ OUT ] - return parameter for newly opened file * * "path" [ IN ] - NUL terminated string in directory-native * character set denoting target file * NOTE: Does not meet a design target of on stack (localized variable) allocation of single 4kb path */ static rc_t CC CCNodeSraDirOpenFileRead (const CCNodeSraDir *self, const KFile **f, const char *path_fmt, va_list args) { rc_t rc; char path[4096]; int size; assert (self != NULL); assert (f != NULL); assert (path_fmt != NULL); size = args ? vsnprintf ( path, sizeof path, path_fmt, args ) : snprintf ( path, sizeof path, "%s", path_fmt ); if ( size < 0 || size >= (int) sizeof path ) return RC (rcFS, rcNoTarg, rcAccessing, rcPath, rcExcessive ); if (CCNodeSraDirLegalPath (self, path)) { rc = KFileAddRef (self->file); if (rc == 0) { *f = self->file; return 0; } return rc; } else rc = RC (rcFS, rcNoTarg, rcAccessing, rcPath, rcNotFound); *f = NULL; return rc; }
static rc_t KBufWriteFileMake ( KBufWriteFile ** bp, const KFile *f, size_t bsize, const KFile_vt *vt, bool read_enabled, bool write_enabled ) { rc_t rc; KBufWriteFile *buf = malloc ( sizeof * buf - 1 + bsize ); if ( buf == NULL ) rc = RC ( rcFS, rcFile, rcConstructing, rcMemory, rcExhausted ); else { memset ( buf, 0, sizeof * buf ); rc = KFileInit ( & buf -> dad, vt, "KBufWriteFile", "no-name", read_enabled, write_enabled ); if ( rc == 0 ) { rc = KFileAddRef ( f ); if ( rc == 0 ) { buf -> f = ( KFile* ) f; buf -> bsize = bsize; * bp = buf; return 0; } } free ( buf ); } return rc; }
static rc_t CCSraInit (CCSra ** pself, CCTree * tree, const KFile * sf, const char * name) { CCSra * self; rc_t rc; assert (pself); assert (sf); assert (name); self = malloc (sizeof (*self)); if (self == NULL) rc = RC (rcExe, rcMemory, rcAllocating, rcMemory, rcExhausted); else { KFileAddRef (self->file = sf); rc = KDirectoryMakeSraNodeDir (&self->ndir, sf, name); if (rc == 0) { rc = KDirectoryOpenSraArchiveReadUnbounded (self->ndir, &self->adir, true, "%s", name); if (rc == 0) { self->tree = tree; *pself = self; return 0; } KDirectoryRelease (self->ndir); } free (self); } return rc; /* error out */ }
static rc_t KSubFileMake (KSubFile ** self, KFile * original, uint64_t start, uint64_t size, bool read_enabled, bool write_enabled) { rc_t rc; KSubFile * pF; /* ----- */ assert (self != NULL); assert (original != NULL); /* assert (start >= size); */ /* ----- * the enables should be true or false */ assert ((read_enabled == true)||(read_enabled == false)); assert ((write_enabled == true)||(write_enabled == false)); /* ----- * get space for the object */ pF = malloc (sizeof (KSubFile)); if (pF == NULL) /* allocation failed */ { /* fail */ rc = RC (rcFS, rcFile, rcConstructing, rcMemory, rcExhausted); } else { rc = KFileInit (&pF->dad, /* initialize base class */ (const KFile_vt*)&vtKSubFile, /* VTable for KSubFile */ "KSubFile", "no-name", read_enabled, /* read allowed */ write_enabled); /* write disallowed */ if (rc == 0) { KFileAddRef (original); /* succeed */ pF->original = original; pF->start = start; pF->size = size; *self = pF; return 0; } /* fail */ free (pF); } return rc; }
KFS_EXTERN rc_t KQuickMountDirMake (const KDirectory * self, const KDirectory ** pnewdir, const KFile * file, const char * path, size_t path_size, const char * mount, size_t mount_size) { KQuickMountDir * newdir; char * pc; rc_t rc; bool endslash; char tbuff [8193]; endslash = path[path_size-1] == '/'; if (sizeof tbuff - 1 < mount_size) return RC (rcFS, rcDirectory, rcCreating, rcBuffer, rcInsufficient); memcpy (tbuff, mount, mount_size); tbuff[mount_size] = '\0'; while ((pc = strpbrk (tbuff, "\"\\/")) != NULL) *pc = '_'; rc = KFileAddRef (file); if (rc == 0) { newdir = KQuickMountDirAlloc (path_size, mount_size); if (newdir == NULL) rc = RC (rcFS, rcDirectory, rcAllocating, rcMemory, rcExhausted); else { newdir->file = file; newdir->mount = newdir->path + path_size; rc = KQuickMountDirMakePath (newdir, rcCreating, true, newdir->path, path_size + 1 + mount_size + 1, endslash?"%s%s":"%s/%s", path, tbuff); if (rc == 0) { rc = KDirectoryInit (&newdir->dad, (const KDirectory_vt*) &vtKQuickMountDir, "KQuickMountDir", path?path:"(null)", false); if (rc == 0) { newdir->mount = newdir->path + path_size + 1; newdir->root = 0; *pnewdir = &newdir->dad; return 0; } /* rc = RC (rcFS, rcDirectory, rcInitializing, rcObject, rcInvalid); */ } KQuickMountDirDestroy (newdir); } } return rc; }
rc_t MMArrayMake(struct MMArray **rslt, KFile *fp, uint32_t elemSize) { MMArray *const self = calloc(1, sizeof(*self)); if (self == NULL) return RC(rcExe, rcMemMap, rcConstructing, rcMemory, rcExhausted); self->elemSize = (elemSize + 3) & ~(3u); /** align to 4 byte **/ self->fp = fp; KFileAddRef(fp); *rslt = self; return 0; }
LIB_EXPORT rc_t CC KLoaderFile_Close(const KLoaderFile* cself) { rc_t rc = 0; if( cself == NULL ) { rc = RC(rcApp, rcFile, rcConstructing, rcParam, rcNull); } else { /* TBD possible delays if file has md5 set */ DBG(("%s closing %s\n", __func__, cself->realname)); rc = KFileRelease(cself->file); KFileAddRef(&cself->dad); ((KLoaderFile*)cself)->file = &cself->dad; } return rc; }
rc_t KFileMakeChunkRead (const struct KFile ** pself, const struct KFile * original, uint64_t size, uint32_t num_chunks, struct KTocChunk * chunks) { rc_t rc; KSubChunkFile * self; /* ----- */ assert (pself != NULL); assert (original != NULL); *pself = NULL; rc = 0; /* ----- * get space for the object */ self = malloc (sizeof (KSubChunkFile) + ((num_chunks-1) * sizeof (KTocChunk))); if (self == NULL) /* allocation failed */ { /* fail */ rc = RC (rcFS, rcFile, rcConstructing, rcMemory, rcExhausted); } else { rc = KFileInit (&self->dad, /* initialize base class */ (const KFile_vt*)&vtKSubChunkFile, /* VTable for KSubChunkFile */ "KSubChunkFile", "no-name", true,false); /* read allowed,write disallowed */ if (rc == 0) { KFileAddRef (original); /* succeed */ self->size = size; self->original = original; self->num_chunks = num_chunks; memcpy ((struct KTocChunk*)self->chunks, chunks, num_chunks * sizeof (KTocChunk)); *pself = &self->dad; return 0; } /* fail */ free (self); } return rc; }
static rc_t KDirectoryMakeSraNodeDir (const KDirectory ** pself, const KFile * file, const char * name) { CCNodeSraDir * self; size_t name_size; rc_t rc; assert (pself); name_size = string_size (name); self = malloc (sizeof (*self) + name_size + 1); if (self == NULL) rc = RC (rcExe, rcNoTarg, rcAllocating, rcMemory, rcExhausted); else { rc = KFileAddRef (file); if (rc == 0) { rc_t orc; self->file = file; self->dir_name = root_name; self->sub_name = (const char *)(self+1); self->name_size = name_size; strcpy ((char*)self->sub_name, name); rc = KDirectoryInit (&self->dad, (const KDirectory_vt*)&CCNodeSraDir_vt, "CCSraNodeDir", root_name, false); if (rc == 0) { *pself = &self->dad; return 0; } orc = KFileRelease (file); if (orc) { PLOGERR (klogErr, (klogErr, orc, "Error releaseing sub file '$(F) in a KAR archive", "F=%s", name)); if (rc == 0) rc = orc; } } } return rc; }
static rc_t CCFileMake (CCFile ** pself, KFile * original, rc_t * prc) { CCFile * self; rc_t rc; /* needs to be better */ assert (pself); assert (original); assert (prc); self = malloc (sizeof (CCFile)); if (self == NULL) /* allocation failed */ { /* fail */ rc = RC (rcFS, rcFile, rcConstructing, rcMemory, rcExhausted); } else { rc = KFileInit (&self->dad, /* initialize base class */ (const KFile_vt*)&vtCCFile,/* VTable for CCFile */ "CCFile", "no-name", original->read_enabled, original->write_enabled); if (rc == 0) { rc = KFileAddRef (original); if (rc == 0) { self->original = original; self->prc = prc; *pself = self; return *prc = 0; } } /* fail */ free (self); } *pself = NULL; *prc = rc; return rc; }
rc_t ProcessOneMake (ProcessOne ** ppo, const KDirectory * dir, KDirectory * xml, const KFile * file, KMD5SumFmt *md5, CCFileFormat * ff, const char * path) { ProcessOne * self; rc_t rc = 0; size_t pathlen; PLOGMSG (klogDebug10, "ProcessOneMake $(f)", PLOG_S(f), path); /* legit seeming inputs? these could be replaced with RC returns */ assert (ppo != NULL); assert (file != NULL); assert (path != NULL); /* allocate the object */ pathlen = strlen (path); self = malloc (sizeof (*self) - sizeof(self->path) + pathlen + 1); if (self == NULL) { rc = RC (rcExe, rcNoTarg, rcAllocating, rcMemory, rcExhausted); } else { atomic32_set (&self->refcount, 1); KDirectoryAddRef (dir); KDirectoryAddRef (xml); KMD5SumFmtAddRef (md5); CCFileFormatAddRef (ff); KFileAddRef (file); self->dir = dir; self->xml = xml; self->md5 = md5; self->file = file; self->ff = ff; memcpy (self->path, path, pathlen); self->path[pathlen] = '\0'; rc = 0; } *ppo = self; return rc; }
/* ---------------------------------------------------------------------- */ static bool CC extract_one (BSTNode * n, void * data_) { extnode * node; rc_data * data = data_; rc_t rc; size_t z; char buff [8193]; assert (n); assert (data); node = (extnode*)n; rc = VPathReadPath (node->path, buff, sizeof (buff) - 1, &z); if (rc) LOGERR (klogErr, rc, "error pulling path for an extraction"); else { const KFile * sfile; buff[z] = '\0'; /* * use base unless we have to revert to root. * base allows more control over options like password where the outside * archive might have a different password than an inner file */ #if 1 rc = VFSManagerOpenFileReadDirectoryRelative (options.vfsmgr, options.base, &sfile, node->path); #else rc = VFSManagerOpenFileReadDirectoryRelative (options.vfsmgr, options.root, &sfile, node->path); #endif if (rc) LOGERR (klogErr, rc, "error opening file within the archive"); else { KFile * dfile; /* KOutMsg ("%s: %s %x\n", __func__, node->path, options.cm); */ rc = KDirectoryCreateFile (options.dir, &dfile, false, 0640, options.cm, "%s", buff); if (rc) PLOGERR (klogErr, (klogErr, rc, "failed to create file '$(P)'", "P=%s", buff)); else { const KFile * teefile; rc = KFileMakeTeeRead (&teefile, sfile, dfile); if (rc) PLOGERR (klogErr, (klogErr, rc, "failed pipefitting file '$(P)'", "P=%s", buff)); else { KFileAddRef (sfile); KFileAddRef (dfile); rc = KFileRelease (teefile); if (rc) PLOGERR (klogErr, (klogErr, rc, "failed copying file '$(P)'", "P=%s", buff)); } } KFileRelease (sfile); } KFileRelease (sfile); } data->rc = rc; return (rc != 0); }
LIB_EXPORT rc_t CC KFileMakeBzip2ForWrite (struct KFile **pnew_obj, struct KFile *compfile) { rc_t rc; if ( pnew_obj == NULL || compfile == NULL ) rc= RC ( rcFS, rcFile, rcConstructing, rcParam, rcNull ); else { KBZipFile *obj; *pnew_obj = NULL; obj = (KBZipFile*)calloc(1,sizeof(KBZipFile)); if (obj == NULL) { rc = RC (rcFS, rcFile, rcConstructing, rcMemory, rcExhausted); LOGERR (klogErr, rc, "memory exhausted building bzip2 " "file object"); } else { rc = KFileInit(&obj->dad, (const KFile_vt*)&KBZipFile_vt_v1, "KBZipFile", "no-name", false, true); if (rc == 0) { bz_stream* strm; int zret; strm = &obj->strm; zret = BZ2_bzCompressInit(strm, 9, /* blockSize100k */ 1, /* verbosity */ 30); /* workFactor */ switch (zret) { case BZ_OK: obj->completed = true; rc = KFileAddRef (compfile); if (rc == 0) { obj->file = compfile; *pnew_obj = &obj->dad; return 0; } break; case BZ_CONFIG_ERROR: rc = RC (rcFS, rcFile, rcConstructing, rcLibrary, rcCorrupt); LOGERR (klogFatal, rc, "bzip2 library miscompiled"); break; case BZ_PARAM_ERROR: rc = RC (rcFS, rcFile, rcConstructing, rcParam, rcInvalid); LOGERR (klogInt, rc, "coding error bzip2 file object"); break; case BZ_MEM_ERROR: rc = RC (rcFS, rcFile, rcConstructing, rcMemory, rcExhausted); LOGERR (klogErr, rc, "memory exhausted building bzip2 " "file object"); break; default: rc = RC (rcFS, rcFile, rcConstructing, rcLibrary, rcUnexpected); LOGERR (klogFatal, rc, "bzip2 library return unexpected " "error"); break; } } } KBZipFileDestroy (obj); } return rc; }
/* MakeWrite * make a queue file for writing-behind on background thread * * when the file is created, a background thread is started that * waits for buffers to appear in the cross-thread queue. as the producer * thread writes, data are accumulated into buffers which are pushed * into the queue as they fill, and written in turn on the bg thread. * * the producer thread is throttled by queue capacity - determined by * "queue_bytes" and "block_size", such that if the queue is full, * the thread will sleep. the background thread is also throttled by * the queue in that it will sleep if the queue is empty with pending * data. * * the background thread will exit upon a permanent error, or if the * queue is sealed by the producer thread. * * when the file is collected in response to a release message, * the queue will be sealed against further inserts, pending buffers * will be written, the background thread will be joined, and * the source file will be released. * * the intended usage is serial writing of the file. random writes * will be accepted, but may reduce the queue efficiency. * * "qf" [ OUT ] - return parameter for queue file * * "dst" [ IN ] - destination file for write-behind on background thread. * must have write permissions. * * "queue_bytes" [ IN ] - the write-behind limit of the producer * thread, in bytes. this is the amount of data that will be queued * for the background thread before the producer thread sleeps. * * "block_size" [ IN, DEFAULT ZERO ] - optional parameter giving * desired block size when writing to "dst". this may be used * to tune writing for source data, e.g. 64K blocks for gzip. */ LIB_EXPORT rc_t CC KQueueFileMakeWrite ( KFile **qfp, KFile *dst, size_t queue_bytes, size_t block_size, uint32_t timeout_ms ) { rc_t rc; if ( qfp == NULL ) rc = RC ( rcApp, rcFile, rcConstructing, rcParam, rcNull ); else { if ( dst == NULL ) rc = RC ( rcApp, rcFile, rcConstructing, rcFile, rcNull ); else if ( ! dst -> write_enabled ) { if ( dst -> read_enabled ) rc = RC ( rcApp, rcFile, rcConstructing, rcFile, rcReadonly ); else rc = RC ( rcApp, rcFile, rcConstructing, rcFile, rcNoPerm ); } else { KQueueFile *qf = malloc ( sizeof * qf ); if ( qf == NULL ) rc = RC ( rcApp, rcFile, rcConstructing, rcMemory, rcExhausted ); else { rc = KFileInit ( & qf -> dad, ( const KFile_vt* ) & KQueueFileWrite_vt_v1, "KQueueFile", "no-name", false, true ); if ( rc == 0 ) { qf -> f = dst; rc = KFileAddRef ( dst ); if ( rc == 0 ) { uint32_t capacity; /* zero block size means default */ if ( block_size == 0 ) block_size = DEFAULT_BLOCK_SIZE; /* queue capacity is expressed in bytes originally translate to buffer count */ capacity = ( queue_bytes + block_size - 1 ) / block_size; if ( capacity == 0 ) capacity = 1; /* actual capacity will be a power of 2 */ rc = KQueueMake ( & qf -> q, capacity ); if ( rc == 0 ) { /* capture current size if supported */ qf -> rc_from_size_on_open = KFileSize ( dst, & qf -> apparent_size ); /* starting position not used */ qf -> start_pos = 0; /* requested buffer size */ qf -> b = NULL; qf -> bsize = block_size; /* timeout */ qf -> timeout_ms = timeout_ms == 0 ? DEFAULT_TIMEOUT_MS : timeout_ms; /* finally, start the background thread */ rc = KThreadMake ( & qf -> t, KQueueFileRunWrite, qf ); if ( rc == 0 ) { * qfp = & qf -> dad; return 0; } KQueueRelease ( qf -> q ); } KFileRelease ( qf -> f ); } } free ( qf ); } } * qfp = NULL; } return rc; }
LIB_EXPORT rc_t CC MakeLogFileV ( struct KDirectory * self, struct KFile const **log_file, struct KFile *to_wrap, bool append, bool timed, const char * path, va_list args ) { rc_t rc = 0; if ( log_file == NULL ) rc = RC ( rcFS, rcFile, rcAllocating, rcParam, rcNull ); else { *log_file = NULL; if ( self == NULL ) rc = RC ( rcFS, rcFile, rcAllocating, rcSelf, rcNull ); else if ( to_wrap == NULL || path == NULL ) rc = RC ( rcFS, rcFile, rcAllocating, rcParam, rcNull ); } if ( rc == 0 ) { rc = KFileAddRef ( to_wrap ); if ( rc == 0 ) { struct Recorder * rec; rc = MakeVRecorder ( self, &rec, 4096, append, path, args ); if ( rc == 0 ) { LogFile * lf = malloc ( sizeof * lf ); if ( lf == NULL ) rc = RC ( rcFS, rcFile, rcConstructing, rcMemory, rcExhausted ); else { /* now we can enter everything into the rr - struct */ lf -> wrapped = to_wrap; lf -> rec = rec; lf -> timed = timed; if ( timed ) { rc = KFileInit ( &lf -> dad, ( const union KFile_vt * ) &vtLogFile_timed, "LogFile", "logfile", true, false ); } else { rc = KFileInit ( &lf -> dad, ( const union KFile_vt * ) &vtLogFile, "LogFile", "logfile", true, false ); } if ( rc != 0 ) free( ( void * ) lf ); else *log_file = ( const KFile * ) &lf -> dad; if ( rc != 0 ) ReleaseRecorder ( rec ); } } if ( rc != 0 ) KFileRelease ( to_wrap ); } } if ( rc != 0 ) { rc = KFileAddRef( to_wrap ); if ( rc == 0 ) *log_file = to_wrap; } return rc; }
/* read only version for decrypting of existing files */ KRYPTO_EXTERN rc_t CC KFileMakeWGAEncRead (const struct KFile ** pself, const struct KFile * encrypted, const char * key, size_t key_size) { rc_t rc; if (pself == NULL) { rc = RC (rcFS, rcFile, rcConstructing, rcSelf, rcNull); LOGERR (klogErr, rc, "key parameter for WGA encrypted file is empty"); return rc; } *pself = NULL; if ((encrypted == NULL)||(key == NULL)) { rc = RC (rcFS, rcFile, rcConstructing, rcParam, rcNull); LOGERR (klogErr, rc, "missing WGA encrypted file passed in to constructor"); } else if (key_size == 0) { rc = RC (rcFS, rcFile, rcConstructing, rcParam, rcInvalid); LOGERR (klogErr, rc, "missing WGA encrypted file passed in to constructor"); } else if (encrypted->read_enabled == 0) { rc = RC (rcFS, rcFile, rcConstructing, rcParam, rcIncorrect); LOGERR (klogErr, rc, "encrypted file not readable"); } else { KCipherManager * cipher_mgr; rc = KCipherManagerMake (&cipher_mgr); if (rc == 0) { KCipher * cipher; rc = KCipherManagerMakeCipher (cipher_mgr, &cipher, kcipher_AES); if (rc == 0) { size_t z; rc = KCipherBlockSize (cipher, &z); if (rc) { LOGERR (klogErr, rc, "unable to get block size for WGA " "encrypted file cipher passed in to constructor"); } else { if (z != ECB_BYTES) { rc = RC (rcFS, rcFile, rcConstructing, rcParam, rcInvalid); LOGERR (klogErr, rc, "wrong block size for WGA " "encrypted file cipher passed in to " "constructor"); } else { KWGAEncFile * self; self = calloc (sizeof (*self), sizeof (uint8_t)); if (self == NULL) { rc = RC (rcFS, rcFile, rcConstructing, rcMemory, rcExhausted); LOGERR (klogErr, rc, "out of memory while " "constructing decryptor"); } else { rc = KFileAddRef (encrypted); if (rc) LOGERR (klogErr, rc, "unable to add reference " "to encrypted file"); else { /* cast to strip const */ self->encrypted = encrypted; self->cipher = cipher; /* read the header of the encrypted file for * details about the decrypted file */ DEBUG_STS(("%s: calling KWGAEncFileHeaderRead\n", __func__)); rc = KWGAEncFileHeaderRead (self); if (rc == 0) { /* using the file header's stored encoding * key build a key from the parameter key */ DEBUG_STS(("%s: calling " "KWGAEncFileHeaderRead\n", __func__)); rc = KWGAEncFileKeyInit (self, key, key_size); } if (rc == 0) { rc = KFileInit (&self->dad, (const KFile_vt*) &vtKWGAEncFileRead, "KWGAEncFile", "no-name", true, false); if (rc) LOGERR (klogInt, rc, "Failed to initialize decrypting file"); else { *pself = &self->dad; self->buffer.offset = 0; self->buffer.valid = 0; KCipherManagerRelease (cipher_mgr); return 0; } } /* release of encrypted handled in destroy() */ } KWGAEncFileDestroyRead (self); } } } KCipherRelease (cipher); } } } return rc; }
rc_t CryptFile (const KFile * in, const KFile ** new_in, KFile * out, KFile ** new_out, EncScheme scheme) { const KFile * dec; rc_t rc; assert (in); assert (out); assert (new_in); assert (new_out); rc = KFileAddRef (out); if (rc) return rc; switch (scheme) { default: case encError: rc = RC (rcExe, rcFile, rcClassifying, rcFile, rcInvalid); break; case encNone: copy: rc = KFileAddRef (in); if (rc) goto fail; *new_in = in; *new_out = out; STSMSG (1, ("not encrypted just copying")); return 0; case encEncFile: rc = KEncFileMakeRead (&dec, in, &Key); made_enc: if (rc) goto fail; switch (ArchiveTypeCheck (dec)) { default: case arcError: rc = RC (rcExe, rcFile, rcClassifying, rcFile, rcInvalid); break; case arcSRAFile: if (!DecryptSraFlag) { rc = KFileRelease (dec); if (rc) { KFileRelease (dec); KFileRelease (in); goto fail; } goto copy; } /* fall through */ case arcNone: *new_out = out; *new_in = dec; return 0; } break; case encWGAEncFile: rc = KFileMakeWGAEncRead (&dec, in, Password, PasswordSize); goto made_enc; break; } fail: KFileRelease (out); *new_in = *new_out = NULL; return rc; }