Пример #1
0
/* 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;
    }
}
Пример #2
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;
}
Пример #3
0
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;
}
Пример #4
0
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 */
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
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;
}
Пример #9
0
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;
}
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
/*  ----------------------------------------------------------------------
 */
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);
}
Пример #14
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;
}
Пример #15
0
/* 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;
}
Пример #16
0
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;
}
Пример #17
0
/* 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; 
}
Пример #18
0
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;
}