Archive-Chm

 view release on metacpan or  search on metacpan

Chm.pm  view on Meta::CPAN

    if (ui->path[0] != '/')
        return CHM_ENUMERATOR_CONTINUE;

    if (snprintf((char*)buffer, sizeof(buffer), "%s%s", ctx->base_path, ui->path) > 1024)
        return CHM_ENUMERATOR_FAILURE;

    if (ui->length != 0)
    {
        FILE *fout;
        LONGINT64 len, remain=ui->length;
        LONGUINT64 offset = 0;

		if (set_verbose("Archive::Chm", -1))
			fprintf(_set_logfile(NULL), "--> %s\n", ui->path);
		if ((fout = fopen((const char*)buffer, "wb")) == NULL)
		{
			/* make sure that it isn't just a missing directory before we abort */ 
			unsigned char newbuf[32768];
			strcpy((char*)newbuf, (const char*)buffer);
			i = rindex((const char*)newbuf, '/');
			*i = '\0';
			_rmkdir((char*)newbuf);
			if ((fout = fopen((const char*)buffer, "wb")) == NULL)
				return CHM_ENUMERATOR_FAILURE;
		}

        while (remain != 0)
        {
            len = chm_retrieve_object(h, ui, buffer, offset, 32768);
            if (len > 0)
            {
                fwrite(buffer, 1, (size_t)len, fout);
                offset += len;
                remain -= len;
            }
            else
            {
                fprintf(stderr, "incomplete file: %s\n", ui->path);
                break;
            }
        }

        fclose(fout);
    }
    else
    {
        if (_rmkdir((char*)buffer) == -1)
            return CHM_ENUMERATOR_FAILURE;
    }

    return CHM_ENUMERATOR_CONTINUE;
}


/*-------------------------------------------------------------------------------
// 	 Function that checks if the file/directory given as an argument exists.
//------------------------------------------------------------------------------*/
static int _dir_exists(const char *path)
{
    struct stat statbuf;
    if (stat(path, &statbuf) != -1)
    	return 1;
    else
    	return 0;
}


/*-------------------------------------------------------------------------------
// 	 Function to make a given directory for use when extracting to a path.
//------------------------------------------------------------------------------*/
static int _rmkdir(char *path)
{
    //strip off trailing components unless we can stat the directory, or we
    //have run out of components

    char *i = rindex(path, '/');

    if(path[0] == '\0'  ||  _dir_exists(path))
        return 0;

    if (i != NULL)
    {
        *i = '\0';
        _rmkdir(path);
        *i = '/';
        mkdir(path, 0777);
    }

#ifdef WIN32
    return 0;
#else
    if (_dir_exists(path))
        return 0;
    else
        return -1;
#endif
}


/*-------------------------------------------------------------------------------
//	Function to set the error message associated with the Archive::Chm object.
//------------------------------------------------------------------------------*/
void _set_errmsg(SV* obj, char* msg)
{
	ChmFile*	chm = (ChmFile*)SvIV(SvRV(obj));
	if (chm->errmsg)
		free(chm->errmsg);
	chm->errmsg = strdup(msg);
}


/*-------------------------------------------------------------------------------
//  Get rid of faulty strndup implementations...
//------------------------------------------------------------------------------*/
static char * my_strndup(const char *src, size_t len)
{
	char *ret = NULL;

	ret = calloc(len + (size_t)1, sizeof(char));
	if ( !ret )
		croak("Out of memory\n");



( run in 1.248 second using v1.01-cache-2.11-cpan-98e64b0badf )