Beispiel #1
0
void u0051_hidlookup__create_file__numbers(
	SG_context* pCtx,
	SG_pathname* pPath,
	const char* pszName,
	const SG_uint32 countLines
	)
{
	SG_pathname* pPathFile = NULL;
	SG_uint32 i;
	SG_file* pFile = NULL;

	VERIFY_ERR_CHECK(  SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPathFile, pPath, pszName)  );
	VERIFY_ERR_CHECK(  SG_file__open__pathname(pCtx, pPathFile, SG_FILE_CREATE_NEW | SG_FILE_RDWR, 0600, &pFile)  );
	for (i=0; i<countLines; i++)
	{
		char buf[64];

		VERIFY_ERR_CHECK(  SG_sprintf(pCtx, buf, sizeof(buf), "%d\n", i)  );
		VERIFY_ERR_CHECK(  SG_file__write(pCtx, pFile, (SG_uint32) strlen(buf), (SG_byte*) buf, NULL)  );
	}
	VERIFY_ERR_CHECK(  SG_file__close(pCtx, &pFile)  );

	SG_PATHNAME_NULLFREE(pCtx, pPathFile);

	return;
fail:
	SG_FILE_NULLCLOSE(pCtx, pFile);
	SG_PATHNAME_NULLFREE(pCtx, pPathFile);
}
/**
 * Export the contents of the given file entry (which reflects a specific version)
 * into a temp file so that an external tool can use it.
 *
 * You own the returned pathname and the file on disk.
 */
void _sg_mrg__export_to_temp_file(SG_context * pCtx, SG_mrg * pMrg,
								  const char * pszHidBlob,
								  const SG_pathname * pPathTempFile)
{
	SG_file * pFile = NULL;
	SG_bool bExists;

	SG_ERR_CHECK(  SG_fsobj__exists__pathname(pCtx,pPathTempFile,&bExists,NULL,NULL)  );
	if (bExists)
	{
#if TRACE_WC_MERGE
		SG_ERR_IGNORE(  SG_console(pCtx,SG_CS_STDERR,
								   "Skipping export of [blob %s] to [%s]\n",pszHidBlob,SG_pathname__sz(pPathTempFile))  );
#endif
	}
	else
	{
#if TRACE_WC_MERGE
		SG_ERR_IGNORE(  SG_console(pCtx,SG_CS_STDERR,
								   "Exporting          [blob %s] to [%s]\n",pszHidBlob,SG_pathname__sz(pPathTempFile))  );
#endif

		// Ideally, when we create this TEMP file it should be read-only.
		// Afterall, it does represent a historical version of the file and
		// it should only be used as INPUT to whatever merge tool the user
		// has configured.  So it should be read-only.  This might allow
		// a GUI merge tool to show locks/whatever and/or prevent accidental
		// editing of these files.
		//
		// However, this can cause an "Access is Denied" error on Windows
		// when we get ready to delete the contents of the TEMP directory.
		// We'll deal with that there rather than here.

		SG_ERR_CHECK(  SG_file__open__pathname(pCtx,pPathTempFile,SG_FILE_WRONLY|SG_FILE_CREATE_NEW,0400,&pFile)  );
		SG_ERR_CHECK(  SG_repo__fetch_blob_into_file(pCtx, pMrg->pWcTx->pDb->pRepo, pszHidBlob,pFile,NULL)  );
		SG_FILE_NULLCLOSE(pCtx,pFile);
	}

	return;

fail:
	if (pFile)			// only if **WE** created the file, do we try to delete it on error.
	{
		SG_FILE_NULLCLOSE(pCtx,pFile);
		SG_ERR_IGNORE(  SG_fsobj__remove__pathname(pCtx,pPathTempFile)  );
	}
}
void SG_unzip__fetch_next_file_into_file(SG_context* pCtx, SG_unzip* punzip, SG_pathname* pPath, SG_bool* pb, const char** ppsz_name, SG_uint64* piLength)
{
   SG_byte* pBytes = NULL;
    SG_uint32 sofar = 0;
    SG_uint32 got = 0;
    SG_file* pFile = NULL;
    SG_bool b = SG_FALSE;
    SG_uint64 len = 0;
    const char* psz_name = NULL;

    SG_ERR_CHECK(  SG_unzip__goto_next_file(pCtx, punzip, &b, &psz_name, &len)  );
    if (!b)
    {
        *pb = SG_FALSE;
        goto done;
    }

	SG_ERR_CHECK(  SG_malloc(pCtx, (SG_uint32)SG_STREAMING_BUFFER_SIZE, &pBytes)  );

    SG_ERR_CHECK(  SG_file__open__pathname(pCtx, pPath, SG_FILE_WRONLY | SG_FILE_CREATE_NEW, 0644, &pFile)  );

    SG_ERR_CHECK(  SG_unzip__currentfile__open(pCtx, punzip)  );
    while (sofar < (SG_uint32) len)
    {
        SG_uint32 want = 0;
        if ((len - sofar) > SG_STREAMING_BUFFER_SIZE)
        {
            want = SG_STREAMING_BUFFER_SIZE;
        }
        else
        {
            want = (SG_uint32) (len - sofar);
        }
        SG_ERR_CHECK(  SG_unzip__currentfile__read(pCtx, punzip, pBytes, want, &got)  );
        if (!got)
        {
            SG_ERR_THROW(  SG_ERR_UNSPECIFIED  ); /* TODO better error */
        }
        SG_ERR_CHECK(  SG_file__write(pCtx, pFile, got, pBytes, NULL)  );

        sofar += got;
    }
    SG_NULLFREE(pCtx, pBytes);
    SG_ERR_CHECK(  SG_file__close(pCtx, &pFile)  );
    SG_ERR_CHECK(  SG_unzip__currentfile__close(pCtx, punzip)  );

    *pb = SG_TRUE;
    *ppsz_name = psz_name;
    *piLength = len;

done:
    /* fall through */

fail:
    SG_FILE_NULLCLOSE(pCtx, pFile);
    SG_NULLFREE(pCtx, pBytes);

}
Beispiel #4
0
void SG_vfile__end(
	SG_context* pCtx,
	SG_vfile** ppvf,
	const SG_vhash* pvh
	)
{
	SG_string* pstr = NULL;
	SG_vfile* pvf = NULL;

	SG_NULLARGCHECK_RETURN(ppvf);

	pvf = *ppvf;

	if (pvh)
	{
		SG_ARGCHECK_RETURN( !(pvf->mode & SG_FILE_RDONLY) , pvh );

		SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pstr)  );

		SG_ERR_CHECK(  SG_vhash__to_json(pCtx, pvh,pstr)  );

		SG_ERR_CHECK(  SG_file__seek(pCtx, pvf->pFile, 0)  );

		SG_ERR_CHECK(  SG_file__truncate(pCtx, pvf->pFile)  );

#if TRACE_VFILE
		SG_ERR_IGNORE(  SG_console(pCtx, SG_CS_STDERR, "VFileEnd: Writing %d bytes to file.\n",
								   SG_string__length_in_bytes(pstr))  );
#endif

		SG_ERR_CHECK(  SG_file__write(pCtx, pvf->pFile, SG_string__length_in_bytes(pstr), (const SG_byte *)SG_string__sz(pstr), NULL)  );
		SG_STRING_NULLFREE(pCtx, pstr);
	}
	else
	{
		if (!(pvf->mode & SG_FILE_RDONLY))
		{
			SG_ERR_CHECK(  SG_file__seek(pCtx, pvf->pFile, 0)  );

			SG_ERR_CHECK(  SG_file__truncate(pCtx, pvf->pFile)  );

#if TRACE_VFILE
			SG_ERR_IGNORE(  SG_console(pCtx, SG_CS_STDERR, "VFileEnd: Truncating file.\n")  );
#endif
		}
	}

	SG_FILE_NULLCLOSE(pCtx, pvf->pFile);

	SG_NULLFREE(pCtx, pvf);
	*ppvf = NULL;

	return;
fail:
	SG_STRING_NULLFREE(pCtx, pstr);
}
Beispiel #5
0
void sg_vfile__dispose(
	SG_context* pCtx,
	SG_vfile* pvf
	)
{
	if (!pvf)
		return;

	SG_FILE_NULLCLOSE(pCtx, pvf->pFile);
	SG_NULLFREE(pCtx, pvf);
}
void SG_random__generate_random_binary_file(SG_context * pCtx, SG_pathname * pPath, SG_uint64 length)
{
	SG_file * pFile = NULL;
	SG_NULLARGCHECK_RETURN(pPath);
	SG_ERR_CHECK(  SG_file__open__pathname(pCtx, pPath, SG_FILE_OPEN_OR_CREATE|SG_FILE_WRONLY,  0644, &pFile)  );
	SG_ERR_CHECK(  SG_random__write_random_bytes_to_file(pCtx, pFile, length)  );
	SG_ERR_CHECK(  SG_file__close(pCtx, &pFile)  );

	return;
fail:
	SG_FILE_NULLCLOSE(pCtx, pFile);
}
void u0038_test_version(SG_context * pCtx)
{
	/* This test pokes around in closet internals in ways normal closet callers shouldn't. */

	SG_string* pstrEnv = NULL;
	SG_uint32 len;
	SG_pathname* pPathCloset = NULL;
	SG_pathname* pPathClosetVersion = NULL;
	SG_pathname* pPathClosetVersionBackup = NULL;
	SG_file* pFile = NULL;
	SG_vhash* pvh = NULL;
	
	/* Deliberately making this break for closet version 3 -- current is version 2. */
	SG_byte buf[3]; 
	
	VERIFY_ERR_CHECK(  SG_environment__get__str(pCtx, "SGCLOSET", &pstrEnv, &len)  );
	if (len)
	{
		VERIFY_ERR_CHECK(  SG_PATHNAME__ALLOC__SZ(pCtx, &pPathCloset, SG_string__sz(pstrEnv))  );
	}
	else
	{
		VERIFY_ERR_CHECK(  SG_PATHNAME__ALLOC__USER_APPDATA_DIRECTORY(pCtx, &pPathCloset)  );
		VERIFY_ERR_CHECK(  SG_pathname__append__from_sz(pCtx, pPathCloset, ".sgcloset")  );
	}

	VERIFY_ERR_CHECK(  SG_pathname__alloc__pathname_sz(pCtx, &pPathClosetVersion, pPathCloset, "version")  );
	VERIFY_ERR_CHECK(  SG_pathname__alloc__pathname_sz(pCtx, &pPathClosetVersionBackup, pPathCloset, "version.bak")  );

	VERIFY_ERR_CHECK(  SG_fsobj__move__pathname_pathname(pCtx, pPathClosetVersion, pPathClosetVersionBackup)  );
	
	VERIFY_ERR_CHECK(  SG_file__open__pathname(pCtx, pPathClosetVersion, SG_FILE_OPEN_OR_CREATE|SG_FILE_WRONLY|SG_FILE_TRUNC, 0644, &pFile)  );
	VERIFY_ERR_CHECK(  SG_file__write(pCtx, pFile, sizeof(buf), buf, NULL)  ); 
	VERIFY_ERR_CHECK(  SG_file__close(pCtx, &pFile)  );

	SG_closet__descriptors__list(pCtx, &pvh);
	VERIFY_COND("", SG_context__err_equals(pCtx, SG_ERR_UNSUPPORTED_CLOSET_VERSION));
	SG_ERR_DISCARD;

	VERIFY_ERR_CHECK(  SG_fsobj__remove__pathname(pCtx, pPathClosetVersion)  );
	VERIFY_ERR_CHECK(  SG_fsobj__move__pathname_pathname(pCtx, pPathClosetVersionBackup, pPathClosetVersion)  );

	/* Common cleanup */
fail:
	SG_STRING_NULLFREE(pCtx, pstrEnv);
	SG_PATHNAME_NULLFREE(pCtx, pPathCloset);
	SG_PATHNAME_NULLFREE(pCtx, pPathClosetVersion);
	SG_PATHNAME_NULLFREE(pCtx, pPathClosetVersionBackup);
	SG_FILE_NULLCLOSE(pCtx, pFile);
	SG_VHASH_NULLFREE(pCtx, pvh);
}
Beispiel #8
0
void _read_template_file(
	SG_context *pCtx,
	const char *templateFn,
	SG_string **pContent,	/**< we allocate, we free on error, else caller owns it */
	const _request_headers *pRequestHeaders,
	_replacer_cb replacer)
{
	SG_pathname *tpath = NULL;
	SG_file *pFile = NULL;
	SG_uint32 got = 0;
	char	tbuf[1024];

    //todo: make this thread-safe:
    if(_sg_uridispatch__templatePath==NULL)
        SG_ERR_CHECK(  _sgui_set_templatePath(pCtx)  );

	SG_ERR_CHECK(  SG_PATHNAME__ALLOC__COPY(pCtx, &tpath, _sg_uridispatch__templatePath)  );
	SG_ERR_CHECK(  SG_pathname__append__from_sz(pCtx, tpath, templateFn)  );

	SG_ERR_CHECK(  SG_file__open__pathname(pCtx, tpath, SG_FILE_RDONLY|SG_FILE_OPEN_EXISTING, 0644, &pFile)  );
	SG_PATHNAME_NULLFREE(pCtx, tpath);

	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, pContent)  );

	do
	{
		SG_file__read(pCtx, pFile, sizeof(tbuf), (SG_byte *)tbuf, &got);
        if (SG_context__err_equals(pCtx, SG_ERR_EOF))
        {
			SG_context__err_reset(pCtx);
            break;
        }
		SG_ERR_CHECK_CURRENT;

		SG_ERR_CHECK(  SG_string__append__buf_len(pCtx, *pContent, (const SG_byte *)tbuf, got) );
	} while (got > 0);

	SG_ERR_CHECK(  SG_file__close(pCtx, &pFile)  );

	SG_ERR_CHECK(  _templatize(pCtx, *pContent, pRequestHeaders, replacer)  );

	return;

fail:
	SG_STRING_NULLFREE(pCtx, *pContent);
	SG_FILE_NULLCLOSE(pCtx, pFile);
	SG_PATHNAME_NULLFREE(pCtx, tpath);
}
Beispiel #9
0
void SG_vfile__abort(
	SG_context* pCtx,
	SG_vfile** ppvf
	)
{
	SG_vfile* pvf = NULL;

	if (!ppvf)
		return;

	pvf = *ppvf;
	if (!pvf)
		return;

	SG_FILE_NULLCLOSE(pCtx, pvf->pFile);
	SG_NULLFREE(pCtx, pvf);

	*ppvf = NULL;
}
Beispiel #10
0
/**
 * Export a blob-of-interest from the REPO into a temporary directory
 * so that we can let the external diff tool compare it with another
 * version somewhere.
 *
 * We create a file with a GID-based name rather than re-creating
 * the working-directory hierarchy in the temp directory.  This lets
 * us flatten the export in one directory without collisions and
 * avoids move/rename and added/deleted sub-directory issues.
 *
 * pPathTempSessionDir should be something like "$TMPDIR/gid_session/".
 * This should be a unique directory name such that everything being
 * exported is isolated from other runs.  (if we are doing a
 * changeset-vs-changeset diff, we may create lots of files on each
 * side -- and our command should not interfere with other diffs
 * in progress in other processes.)
 *
 * szVersion should be a value to let us group everything from cset[0]
 * in a different directory from stuff from cset[1].  this might be
 * simply "0" and "1" or it might be the cset's HIDs.
 *
 * szGidObject is the gid of the object.
 *
 * szHidBlob is the HID of the content.  Normally this is the content
 * of the file that will be compared (corresponding to a user-file
 * under version control).  However, we may also want to use this
 * to splat the XATTRs to a file so that they can be compared (on
 * non-apple systems) -- but this may be too weird.
 *
 * You are responsible for freeing the returned pathname and
 * deleting the file that we create.
 */
void SG_diff_utils__export_to_temp_file(SG_context * pCtx,
										SG_repo * pRepo,
										const SG_pathname * pPathTempSessionDir,	// value of "$TMPDIR/session/"
										const char * szVersion,						// an index (like 0 or 1, _older_ _newer_) or maybe cset HID
										const char * szGidObject,
										const char * szHidBlob,
										SG_pathname ** ppPathTempFile)
{
	SG_pathname * pPathFile = NULL;
	SG_file * pFile = NULL;
	SG_bool bDirExists;

	// mkdir $TMPDIR/session/version
	// create pathname for the temp file: $TMPDIR/session/version/object_gid
	//
	// TODO do we want to append the suffix from the file to this pathname so that
	// TODO tools like SGDM can use it?  what if the file is renamed and given a
	// TODO different suffix between versions?

	SG_ERR_CHECK(  SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx,&pPathFile,pPathTempSessionDir,szVersion)  );
	SG_ERR_CHECK(  SG_fsobj__exists__pathname(pCtx,pPathFile,&bDirExists,NULL,NULL)  );
	if (!bDirExists)
		SG_ERR_CHECK(  SG_fsobj__mkdir_recursive__pathname(pCtx,pPathFile)  );
	SG_ERR_CHECK(  SG_pathname__append__from_sz(pCtx,pPathFile,szGidObject)  );

	// open the file and copy the contents of the blob into it

	SG_ERR_CHECK(  SG_file__open__pathname(pCtx,pPathFile,SG_FILE_WRONLY|SG_FILE_CREATE_NEW,0600,&pFile)  );
	SG_ERR_CHECK(  SG_repo__fetch_blob_into_file(pCtx,pRepo,szHidBlob,pFile,NULL)  );
	SG_ERR_CHECK(  SG_file__close(pCtx,&pFile)  );

	*ppPathTempFile = pPathFile;
	return;

fail:
	if (pFile)				// only if **WE** created the file, do we try to delete it on an error.
	{
		SG_FILE_NULLCLOSE(pCtx,pFile);
		SG_ERR_IGNORE(  SG_fsobj__remove__pathname(pCtx,pPathFile)  );
	}
	SG_PATHNAME_NULLFREE(pCtx, pPathFile);
}
Beispiel #11
0
void SG_vfile__begin(
	SG_context* pCtx,
	const SG_pathname* pPath, /**< The path of the file containing the JSON text */
	SG_file_flags mode,
	SG_vhash** ppvh, /**< If there are no errors, the resulting vhash table will be returned here. */
	SG_vfile** ppvf
	)
{
	SG_vfile* pvf = NULL;
	SG_vhash* pvh = NULL;
	SG_uint32 len32;
	SG_fsobj_type t;
	SG_byte* p = NULL;
	SG_bool bExists;
	SG_fsobj_type FsObjType;
	SG_fsobj_perms FsObjPerms;

	SG_ERR_CHECK(  SG_fsobj__exists__pathname(pCtx, pPath, &bExists, &FsObjType, &FsObjPerms)  );

	if (
		bExists
		&& (SG_FSOBJ_TYPE__REGULAR != FsObjType)
		)
	{
		SG_ERR_THROW_RETURN(SG_ERR_NOTAFILE);
	}

	if (bExists)
	{
		SG_uint64 len64;
		SG_ERR_CHECK(  SG_fsobj__length__pathname(pCtx, pPath, &len64, &t)  );

		// TODO "len" is uint64 because we can have huge files, but
		// TODO our buffer is limited to uint32 (on 32bit systems).
		// TODO verify that len will fit in uint32.
		len32 = (SG_uint32)len64;
	}
	else
	{
		len32 = 0;
	}

	SG_ERR_CHECK_RETURN(  SG_alloc1(pCtx, pvf)  );

	SG_ERR_CHECK(  SG_file__open__pathname(pCtx, pPath, mode | SG_FILE_LOCK, SG_FSOBJ_PERMS__UNUSED, &pvf->pFile)  );

	pvf->mode = mode;

#if TRACE_VFILE
	SG_ERR_IGNORE(  SG_console(pCtx, SG_CS_STDERR, "VFileBegin: Reading %d bytes from %s\n", len32, SG_pathname__sz(pPath))  );
#endif

	if (len32 > 0)
	{
		SG_ERR_CHECK(  SG_alloc(pCtx, 1,len32+1,&p)  );
		SG_ERR_CHECK(  SG_file__read(pCtx, pvf->pFile, len32, p, NULL)  );

		p[len32] = 0;

		SG_ERR_CHECK(  SG_VHASH__ALLOC__FROM_JSON(pCtx, &pvh, (const char*) p)  );

		SG_NULLFREE(pCtx, p);
		p = NULL;
	}
	else
	{
		pvh = NULL;
	}

	*ppvf = pvf;
	*ppvh = pvh;

	return;

fail:
	SG_FILE_NULLCLOSE(pCtx, pvf->pFile);
	SG_NULLFREE(pCtx, p);
	SG_NULLFREE(pCtx, pvf);
}
static void sg_read_entire_file(
	SG_context* pCtx,
	const SG_pathname* pPath,
	char** ppbuf,
	SG_uint32* plen
	)
{
	SG_uint32 len32;
	SG_fsobj_type t;
	SG_byte* p = NULL;
	SG_bool bExists;
	SG_fsobj_type FsObjType;
	SG_fsobj_perms FsObjPerms;
	SG_file* pFile = NULL;

	SG_ERR_CHECK(  SG_fsobj__exists__pathname(pCtx, pPath, &bExists, &FsObjType, &FsObjPerms)  );

	if (
		bExists
		&& (SG_FSOBJ_TYPE__REGULAR != FsObjType)
		)
	{
		SG_ERR_IGNORE(  SG_log__report_error(pCtx, "Unable to open file: %s.", SG_pathname__sz(pPath))  );
		
		SG_ERR_THROW_RETURN(SG_ERR_NOTAFILE);
	}

	if (bExists)
	{
		SG_uint64 len64;
		SG_ERR_CHECK(  SG_fsobj__length__pathname(pCtx, pPath, &len64, &t)  );

		// TODO "len" is uint64 because we can have huge files, but
		// TODO our buffer is limited to uint32 (on 32bit systems).
		// TODO verify that len will fit in uint32.
		len32 = (SG_uint32)len64;

		SG_ERR_CHECK(  SG_file__open__pathname(pCtx, pPath, SG_FILE_RDONLY | SG_FILE_OPEN_EXISTING, SG_FSOBJ_PERMS__UNUSED, &pFile)  );
	}
	else
	{
		SG_ERR_THROW_RETURN(SG_ERR_NOTAFILE);
		//len32 = 0;
	}

	if (len32 > 0)
	{
		SG_ERR_CHECK(  SG_alloc(pCtx, 1,len32+1,&p)  );
		SG_ERR_CHECK(  SG_file__read(pCtx, pFile, len32, p, NULL)  );

		p[len32] = 0;

		*ppbuf = (char*) p;
		p = NULL;
		*plen = len32;
	}
	else
	{
		*ppbuf = NULL;
		*plen = 0;
	}

fail:
	SG_FILE_NULLCLOSE(pCtx, pFile);
	SG_NULLFREE(pCtx, p);
}
void SG_unzip__open(SG_context* pCtx, const SG_pathname* pPath, SG_unzip** ppResult)
{
    SG_unzip us;
    SG_unzip *s;
    SG_uint64 central_pos = 0;
    SG_uint32 uL;

    SG_uint16 number_disk = 0;          /* number of the current dist, used for
                                   spaning ZIP, unsupported, always 0*/
    SG_uint16 number_disk_with_CD = 0;  /* number the the disk with central dir, used
                                   for spaning ZIP, unsupported, always 0*/
    SG_uint16 number_entry_CD = 0;      /* total number of entries in
                                   the central dir
                                   (same than number_entry on nospan) */


    SG_ERR_CHECK(  SG_file__open__pathname(pCtx, pPath, SG_FILE_RDONLY | SG_FILE_OPEN_EXISTING, SG_FSOBJ_PERMS__UNUSED, &us.pFile)  );

    SG_ERR_CHECK(  sg_unzip__locate_central_dir(pCtx, us.pFile, &central_pos)  );

    SG_ERR_CHECK(  SG_file__seek(pCtx, us.pFile, central_pos)  );

    /* the signature, already checked */
    SG_ERR_CHECK(  sg_unzip__get_uint32(pCtx, us.pFile,&uL)  );

    /* number of this disk */
    SG_ERR_CHECK(  sg_unzip__get_uint16(pCtx, us.pFile,&number_disk)  );

    /* number of the disk with the start of the central directory */
    SG_ERR_CHECK(  sg_unzip__get_uint16(pCtx, us.pFile,&number_disk_with_CD)  );

    /* total number of entries in the central dir on this disk */
    SG_ERR_CHECK(  sg_unzip__get_uint16(pCtx, us.pFile,&us.gi.number_entry)  );

    /* total number of entries in the central dir */
    SG_ERR_CHECK(  sg_unzip__get_uint16(pCtx, us.pFile,&number_entry_CD)  );

    if ((number_entry_CD!=us.gi.number_entry) ||
        (number_disk_with_CD!=0) ||
        (number_disk!=0))
    {
        SG_ERR_THROW(  SG_ERR_ZIP_BAD_FILE  );
    }

    /* size of the central directory */
    SG_ERR_CHECK(  sg_unzip__get_uint32(pCtx, us.pFile,&us.size_central_dir)  );

    /* offset of start of central directory with respect to the
          starting disk number */
    SG_ERR_CHECK(  sg_unzip__get_uint32(pCtx, us.pFile,&us.offset_central_dir)  );

    /* zipfile comment length */
    SG_ERR_CHECK(  sg_unzip__get_uint16(pCtx, us.pFile,&us.gi.size_comment)  );

    if (central_pos<us.offset_central_dir+us.size_central_dir)
    {
        SG_ERR_THROW(  SG_ERR_ZIP_BAD_FILE  );
    }

    us.byte_before_the_zipfile = (SG_uint32) (central_pos - (us.offset_central_dir+us.size_central_dir));
    us.central_pos = central_pos;
    us.pfile_in_zip_read = NULL;

    us.current_file_ok = SG_FALSE;

	SG_ERR_CHECK(  SG_malloc(pCtx, sizeof(SG_unzip), &s)  );
    *s=us;

    *ppResult = s;

    return;

fail:
    /* TODO free stuff */
    SG_FILE_NULLCLOSE(pCtx, us.pFile);
}
Beispiel #14
0
int u0040_unc__stat_dir(SG_context * pCtx, const char * szDir)
{
	SG_pathname * pPathname = NULL;
	SG_pathname * pPathnameFile = NULL;
	SG_file * pf = NULL;
	SG_fsobj_stat fsobjStat;
	SG_bool bFileExists;
	SG_int_to_string_buffer bufSize;
	char bufDate[100];

	SG_context__err_reset(pCtx);

	//////////////////////////////////////////////////////////////////
	// stat the given directory.
	//////////////////////////////////////////////////////////////////

	INFOP("u0040_unc",("Inspecting [%s]",szDir));

	VERIFY_ERR_CHECK_RETURN(  SG_PATHNAME__ALLOC__SZ(pCtx,&pPathname,szDir)  );

	VERIFY_ERR_CHECK(  SG_fsobj__stat__pathname(pCtx,pPathname,&fsobjStat)  );
	VERIFY_COND("u0040_unc",(fsobjStat.type == SG_FSOBJ_TYPE__DIRECTORY));

	// TODO should we verify length == 0 ?
	// TODO should we verify modtime ?

	SG_uint64_to_sz(fsobjStat.size, bufSize);
	VERIFY_ERR_CHECK_DISCARD(  SG_time__format_utc__i64(pCtx,fsobjStat.mtime_ms,bufDate,SG_NrElements(bufDate))  );

	INFOP("u0040_unc",("Result: [perms %04o][type %d][size %s][mtime %s]",
					   fsobjStat.perms,fsobjStat.type,
					   bufSize,bufDate));

	//////////////////////////////////////////////////////////////////
	// create a unique file in the directory and stat it.
	//////////////////////////////////////////////////////////////////

	VERIFY_ERR_CHECK(  unittest__alloc_unique_pathname(pCtx,szDir,&pPathnameFile)  );

	INFOP("u0040_unc",("    Creating file [%s]",SG_pathname__sz(pPathnameFile)));

	VERIFY_ERR_CHECK(  SG_file__open__pathname(pCtx,pPathnameFile,SG_FILE_CREATE_NEW | SG_FILE_RDWR,0777,&pf)  );

	VERIFY_ERR_CHECK(  SG_fsobj__stat__pathname(pCtx,pPathnameFile,&fsobjStat)  );
	VERIFY_COND("u0040_unc",(fsobjStat.type == SG_FSOBJ_TYPE__REGULAR));
	VERIFY_COND("u0040_unc",(fsobjStat.size == 0));
	VERIFY_COND("u0040_unc",(SG_fsobj__equivalent_perms(fsobjStat.perms,0777)));
	// TODO should we verify modtime ?

	SG_uint64_to_sz(fsobjStat.size, bufSize);
	VERIFY_ERR_CHECK_DISCARD(  SG_time__format_utc__i64(pCtx,fsobjStat.mtime_ms,bufDate,SG_NrElements(bufDate))  );

	INFOP("u0040_unc",("    Result: [perms %04o][type %d][size %s][mtime %s]",
					   fsobjStat.perms,fsobjStat.type,
					   bufSize,bufDate));

	VERIFY_ERR_CHECK_DISCARD(  SG_file__close(pCtx, &pf)  );

	// delete the file and stat it again

	VERIFY_ERR_CHECK_DISCARD(  SG_fsobj__remove__pathname(pCtx,pPathnameFile)  );
	VERIFY_ERR_CHECK_DISCARD(  SG_fsobj__exists__pathname(pCtx,pPathnameFile,&bFileExists,NULL,NULL)  );
	VERIFY_COND("u0040_unc",(!bFileExists));

	//////////////////////////////////////////////////////////////////
	// clean up
	//////////////////////////////////////////////////////////////////

	SG_PATHNAME_NULLFREE(pCtx, pPathnameFile);
	SG_PATHNAME_NULLFREE(pCtx, pPathname);
	return 1;

fail:
	SG_FILE_NULLCLOSE(pCtx, pf);
	SG_PATHNAME_NULLFREE(pCtx, pPathnameFile);
	SG_PATHNAME_NULLFREE(pCtx, pPathname);
	return 0;
}
/**
 * create 1 test file.
 * cat it to a second file using files bound to child's STDIN and STDOUT.
 * cat both files to third file using cl args for input and third bound to child's STDOUT.
 * cat all 3 files using cl args to OUR STDOUT.
 */
void MyFn(test1)(SG_context * pCtx)
{
	SG_exit_status exitStatusChild;
	SG_file * pFileF1 = NULL;
	SG_file * pFileF2 = NULL;
	SG_file * pFileF3 = NULL;
	SG_pathname * pPathTempDir = NULL;
	SG_pathname * pPathF1 = NULL;
	SG_pathname * pPathF2 = NULL;
	SG_pathname * pPathF3 = NULL;
	SG_exec_argvec * pArgVec = NULL;

	// create a GID temp directory in the current directory.

	VERIFY_ERR_CHECK(  unittest__alloc_unique_pathname_in_cwd(pCtx,&pPathTempDir)  );
	VERIFY_ERR_CHECK(  SG_fsobj__mkdir_recursive__pathname(pCtx,pPathTempDir)  );

	// create a couple of pathnames to test files in the temp directory.

	VERIFY_ERR_CHECK(  unittest__alloc_unique_pathname_in_dir(pCtx,SG_pathname__sz(pPathTempDir),&pPathF1)  );
	INFOP("exec",("PathF1 is %s",SG_pathname__sz(pPathF1)));
	VERIFY_ERR_CHECK(  unittest__alloc_unique_pathname_in_dir(pCtx,SG_pathname__sz(pPathTempDir),&pPathF2)  );
	INFOP("exec",("PathF2 is %s",SG_pathname__sz(pPathF2)));
	VERIFY_ERR_CHECK(  unittest__alloc_unique_pathname_in_dir(pCtx,SG_pathname__sz(pPathTempDir),&pPathF3)  );
	INFOP("exec",("PathF3 is %s",SG_pathname__sz(pPathF3)));

	//////////////////////////////////////////////////////////////////
	// create F1 and write some data to it.

	VERIFY_ERR_CHECK(  SG_file__open__pathname(pCtx,pPathF1,SG_FILE_WRONLY|SG_FILE_CREATE_NEW,0644,&pFileF1)  );
	VERIFY_ERR_CHECK(  SG_file__write(pCtx,pFileF1,
									  SG_pathname__length_in_bytes(pPathF1),
									  (SG_byte *)SG_pathname__sz(pPathF1),
									  NULL)  );
	VERIFY_ERR_CHECK(  SG_file__write(pCtx,pFileF1,
									  1,
									  (SG_byte *)"\n",
									  NULL)  );
	VERIFY_ERR_CHECK(  SG_file__write(pCtx,pFileF1,
									  SG_pathname__length_in_bytes(pPathF1),
									  (SG_byte *)SG_pathname__sz(pPathF1),
									  NULL)  );
	VERIFY_ERR_CHECK(  SG_file__write(pCtx,pFileF1,
									  1,
									  (SG_byte *)"\n",
									  NULL)  );
	SG_FILE_NULLCLOSE(pCtx, pFileF1);

	//////////////////////////////////////////////////////////////////
	// re-open F1 for reading.
	// create F2 as a place for STDOUT of command.

	VERIFY_ERR_CHECK(  SG_file__open__pathname(pCtx,pPathF1,SG_FILE_RDONLY|SG_FILE_OPEN_EXISTING,0644,&pFileF1)  );
	VERIFY_ERR_CHECK(  SG_file__open__pathname(pCtx,pPathF2,SG_FILE_WRONLY|SG_FILE_CREATE_NEW,   0644,&pFileF2)  );

	// exec: /bin/cat <f1 >f2

	VERIFY_ERR_CHECK(  SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,NULL,pFileF1,pFileF2,NULL,&exitStatusChild)  );
	VERIFY_COND("child status",(exitStatusChild == 0));

	INFOP("/bin/cat <f1 >f2",("Child exit status is [%d]",exitStatusChild));
	SG_FILE_NULLCLOSE(pCtx, pFileF1);
	SG_FILE_NULLCLOSE(pCtx, pFileF2);

	//////////////////////////////////////////////////////////////////
	// let F1 and F2 be given on the command line.
	// create F3 as a place for STDOUT of command.

	VERIFY_ERR_CHECK(  SG_file__open__pathname(pCtx,pPathF3,SG_FILE_WRONLY|SG_FILE_CREATE_NEW,   0644,&pFileF3)  );

	// exec: /bin/cat -n f1 f2 >f3

	VERIFY_ERR_CHECK(  SG_exec_argvec__alloc(pCtx,&pArgVec)  );
	VERIFY_ERR_CHECK(  SG_exec_argvec__append__sz(pCtx,pArgVec,"-n")  );
	VERIFY_ERR_CHECK(  SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF1))  );
	VERIFY_ERR_CHECK(  SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF2))  );

	VERIFY_ERR_CHECK(  SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,pArgVec,NULL,pFileF3,NULL,&exitStatusChild)  );
	VERIFY_COND("child status",(exitStatusChild == 0));

	INFOP("/bin/cat -n f1 f2 >f3",("Child exit status is [%d]",exitStatusChild));
	SG_FILE_NULLCLOSE(pCtx, pFileF3);
	SG_EXEC_ARGVEC_NULLFREE(pCtx, pArgVec);

	//////////////////////////////////////////////////////////////////
	// exec: /bin/cat f1 f2 f3 (to our stdout)

	VERIFY_ERR_CHECK(  SG_exec_argvec__alloc(pCtx,&pArgVec)  );
	VERIFY_ERR_CHECK(  SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF1))  );
	VERIFY_ERR_CHECK(  SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF2))  );
	VERIFY_ERR_CHECK(  SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF3))  );

	VERIFY_ERR_CHECK(  SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,pArgVec,NULL,NULL,NULL,&exitStatusChild)  );
	VERIFY_COND("child status",(exitStatusChild == 0));

	INFOP("/bin/cat -n f1 f2 f3",("Child exit status is [%d]",exitStatusChild));
	SG_EXEC_ARGVEC_NULLFREE(pCtx, pArgVec);

	//////////////////////////////////////////////////////////////////
	// exec: /bin/cat f3 f2 f1 (to our stdout)

	VERIFY_ERR_CHECK(  SG_exec_argvec__alloc(pCtx,&pArgVec)  );
	VERIFY_ERR_CHECK(  SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF3))  );
	VERIFY_ERR_CHECK(  SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF2))  );
	VERIFY_ERR_CHECK(  SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF1))  );

	VERIFY_ERR_CHECK(  SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,pArgVec,NULL,NULL,NULL,&exitStatusChild)  );
	VERIFY_COND("child status",(exitStatusChild == 0));

	INFOP("/bin/cat -n f3 f2 f1",("Child exit status is [%d]",exitStatusChild));
	SG_EXEC_ARGVEC_NULLFREE(pCtx, pArgVec);

	// fall through to common cleanup.

fail:
	SG_EXEC_ARGVEC_NULLFREE(pCtx, pArgVec);
	SG_PATHNAME_NULLFREE(pCtx, pPathTempDir);
	SG_PATHNAME_NULLFREE(pCtx, pPathF1);
	SG_PATHNAME_NULLFREE(pCtx, pPathF2);
	SG_PATHNAME_NULLFREE(pCtx, pPathF3);
	SG_FILE_NULLCLOSE(pCtx, pFileF1);
	SG_FILE_NULLCLOSE(pCtx, pFileF2);
	SG_FILE_NULLCLOSE(pCtx, pFileF3);
}
/**
 * create 1 test file.
 * cat it to a second file using files bound to child's STDIN and STDOUT.
 * repeat using still open files.
 * verify that we get an append effect.
 *
 * do this again using input file on the command line into a third file.
 */
void MyFn(test2)(SG_context * pCtx)
{
	SG_exit_status exitStatusChild;
	SG_file * pFileF1 = NULL;
	SG_file * pFileF2 = NULL;
	SG_file * pFileF3 = NULL;
	SG_pathname * pPathTempDir = NULL;
	SG_pathname * pPathF1 = NULL;
	SG_pathname * pPathF2 = NULL;
	SG_pathname * pPathF3 = NULL;
	SG_exec_argvec * pArgVec = NULL;
	SG_uint64 lenFileF1, lenFileF2, lenFileF3;
	SG_uint64 posFileF1, posFileF2, posFileF3;

	// create a GID temp directory in the current directory.

	VERIFY_ERR_CHECK(  unittest__alloc_unique_pathname_in_cwd(pCtx,&pPathTempDir)  );
	VERIFY_ERR_CHECK(  SG_fsobj__mkdir_recursive__pathname(pCtx,pPathTempDir)  );

	// create a couple of pathnames to test files in the temp directory.

	VERIFY_ERR_CHECK(  unittest__alloc_unique_pathname_in_dir(pCtx,SG_pathname__sz(pPathTempDir),&pPathF1)  );
	INFOP("exec",("PathF1 is %s",SG_pathname__sz(pPathF1)));
	VERIFY_ERR_CHECK(  unittest__alloc_unique_pathname_in_dir(pCtx,SG_pathname__sz(pPathTempDir),&pPathF2)  );
	INFOP("exec",("PathF2 is %s",SG_pathname__sz(pPathF2)));
	VERIFY_ERR_CHECK(  unittest__alloc_unique_pathname_in_dir(pCtx,SG_pathname__sz(pPathTempDir),&pPathF3)  );
	INFOP("exec",("PathF3 is %s",SG_pathname__sz(pPathF3)));

	//////////////////////////////////////////////////////////////////
	// create F1 and write some data to it.

	VERIFY_ERR_CHECK(  SG_file__open__pathname(pCtx,pPathF1,SG_FILE_WRONLY|SG_FILE_CREATE_NEW,0644,&pFileF1)  );
	VERIFY_ERR_CHECK(  SG_file__write(pCtx,pFileF1,
									  SG_pathname__length_in_bytes(pPathF1),
									  (SG_byte *)SG_pathname__sz(pPathF1),
									  NULL)  );
	VERIFY_ERR_CHECK(  SG_file__write(pCtx,pFileF1,
									  1,
									  (SG_byte *)"\n",
									  NULL)  );
	SG_FILE_NULLCLOSE(pCtx, pFileF1);

	// get length of F1 as created on disk.

	VERIFY_ERR_CHECK(  SG_fsobj__length__pathname(pCtx,pPathF1,&lenFileF1,NULL)  );
	INFOP("lenCheck",("Length F1[%d]",(SG_uint32)lenFileF1));
	VERIFY_COND("lenCheck",(lenFileF1 > 0));

	//////////////////////////////////////////////////////////////////
	// re-open F1 for reading.
	// create F2 as a place for STDOUT of command.

	VERIFY_ERR_CHECK(  SG_file__open__pathname(pCtx,pPathF1,SG_FILE_RDONLY|SG_FILE_OPEN_EXISTING,0644,&pFileF1)  );
	VERIFY_ERR_CHECK(  SG_file__open__pathname(pCtx,pPathF2,SG_FILE_WRONLY|SG_FILE_CREATE_NEW,   0644,&pFileF2)  );

	// exec: "/bin/cat <f1 >f2" three times holding the file handles open between runs.

	VERIFY_ERR_CHECK(  SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,NULL,pFileF1,pFileF2,NULL,&exitStatusChild)  );
	VERIFY_COND("child status",(exitStatusChild == 0));
	INFOP("/bin/cat <f1 >f2",("Child exit status is [%d]",exitStatusChild));
	VERIFY_ERR_CHECK(  SG_file__tell(pCtx,pFileF1,&posFileF1)  );
	VERIFY_ERR_CHECK(  SG_file__tell(pCtx,pFileF2,&posFileF2)  );
	INFOP("tell",("Position F1[%d] Position F2[%d]",(SG_uint32)posFileF1,(SG_uint32)posFileF2));
	VERIFY_COND("tell",(posFileF1 == lenFileF1));		// child has dup'd version of handles and so we share seek positions.
	VERIFY_COND("tell",(posFileF2 == posFileF1));		// so, the child should have caused our position to change.

	VERIFY_ERR_CHECK(  SG_file__seek(pCtx,pFileF1,0)  );

	VERIFY_ERR_CHECK(  SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,NULL,pFileF1,pFileF2,NULL,&exitStatusChild)  );
	VERIFY_COND("child status",(exitStatusChild == 0));
	INFOP("/bin/cat <f1 >f2",("Child exit status is [%d]",exitStatusChild));
	VERIFY_ERR_CHECK(  SG_file__tell(pCtx,pFileF1,&posFileF1)  );
	VERIFY_ERR_CHECK(  SG_file__tell(pCtx,pFileF2,&posFileF2)  );
	INFOP("tell",("Position F1[%d] Position F2[%d]",(SG_uint32)posFileF1,(SG_uint32)posFileF2));
	VERIFY_COND("tell",(posFileF1 == lenFileF1));		// child has dup'd version of handles and so we share seek positions.
	VERIFY_COND("tell",(posFileF2 == 2*posFileF1));		// so, the child should have caused our position to change.

	VERIFY_ERR_CHECK(  SG_file__seek(pCtx,pFileF1,0)  );

	VERIFY_ERR_CHECK(  SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,NULL,pFileF1,pFileF2,NULL,&exitStatusChild)  );
	VERIFY_COND("child status",(exitStatusChild == 0));
	INFOP("/bin/cat <f1 >f2",("Child exit status is [%d]",exitStatusChild));
	VERIFY_ERR_CHECK(  SG_file__tell(pCtx,pFileF1,&posFileF1)  );
	VERIFY_ERR_CHECK(  SG_file__tell(pCtx,pFileF2,&posFileF2)  );
	INFOP("tell",("Position F1[%d] Position F2[%d]",(SG_uint32)posFileF1,(SG_uint32)posFileF2));
	VERIFY_COND("tell",(posFileF1 == lenFileF1));		// child has dup'd version of handles and so we share seek positions.
	VERIFY_COND("tell",(posFileF2 == 3*posFileF1));		// so, the child should have caused our position to change.

	SG_FILE_NULLCLOSE(pCtx, pFileF1);
	SG_FILE_NULLCLOSE(pCtx, pFileF2);

	// get length of F2 and see how it compares with F1.

	VERIFY_ERR_CHECK(  SG_fsobj__length__pathname(pCtx,pPathF2,&lenFileF2,NULL)  );
	INFOP("lenCheck",("Length F1[%d] Length F2[%d]",(SG_uint32)lenFileF1,(SG_uint32)lenFileF2));
	VERIFY_COND("lenCheck",(lenFileF2 == 3*lenFileF1));

	//////////////////////////////////////////////////////////////////
	// let F1 be given on the command line.
	// create F3 as a place for STDOUT of command.

	VERIFY_ERR_CHECK(  SG_file__open__pathname(pCtx,pPathF3,SG_FILE_WRONLY|SG_FILE_CREATE_NEW,   0644,&pFileF3)  );

	// exec: "/bin/cat f1 >f3" three times holding F3 open between runs.

	VERIFY_ERR_CHECK(  SG_exec_argvec__alloc(pCtx,&pArgVec)  );
	VERIFY_ERR_CHECK(  SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF1))  );

	VERIFY_ERR_CHECK(  SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,pArgVec,NULL,pFileF3,NULL,&exitStatusChild)  );
	VERIFY_COND("child status",(exitStatusChild == 0));
	INFOP("/bin/cat f1 >f3",("Child exit status is [%d]",exitStatusChild));
	VERIFY_ERR_CHECK(  SG_file__tell(pCtx,pFileF3,&posFileF3)  );
	INFOP("tell",("Position F3[%d]",(SG_uint32)posFileF3));
	VERIFY_COND("tell",(posFileF3 == lenFileF1));

	VERIFY_ERR_CHECK(  SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,pArgVec,NULL,pFileF3,NULL,&exitStatusChild)  );
	VERIFY_COND("child status",(exitStatusChild == 0));
	INFOP("/bin/cat f1 >f3",("Child exit status is [%d]",exitStatusChild));
	VERIFY_ERR_CHECK(  SG_file__tell(pCtx,pFileF3,&posFileF3)  );
	INFOP("tell",("Position F3[%d]",(SG_uint32)posFileF3));
	VERIFY_COND("tell",(posFileF3 == 2*lenFileF1));

	VERIFY_ERR_CHECK(  SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,pArgVec,NULL,pFileF3,NULL,&exitStatusChild)  );
	VERIFY_COND("child status",(exitStatusChild == 0));
	INFOP("/bin/cat f1 >f3",("Child exit status is [%d]",exitStatusChild));
	VERIFY_ERR_CHECK(  SG_file__tell(pCtx,pFileF3,&posFileF3)  );
	INFOP("tell",("Position F3[%d]",(SG_uint32)posFileF3));
	VERIFY_COND("tell",(posFileF3 == 3*lenFileF1));

	SG_FILE_NULLCLOSE(pCtx, pFileF3);

	// get length of F3 and see how it compares with F1.

	VERIFY_ERR_CHECK(  SG_fsobj__length__pathname(pCtx,pPathF3,&lenFileF3,NULL)  );
	INFOP("lenCheck",("Length F1[%d] Length F3[%d]",(SG_uint32)lenFileF1,(SG_uint32)lenFileF3));
	VERIFY_COND("tell",(lenFileF3 == 3*lenFileF1));

	//////////////////////////////////////////////////////////////////

	// fall through to common cleanup.

fail:
	SG_EXEC_ARGVEC_NULLFREE(pCtx, pArgVec);
	SG_PATHNAME_NULLFREE(pCtx, pPathTempDir);
	SG_PATHNAME_NULLFREE(pCtx, pPathF1);
	SG_PATHNAME_NULLFREE(pCtx, pPathF2);
	SG_PATHNAME_NULLFREE(pCtx, pPathF3);
	SG_FILE_NULLCLOSE(pCtx, pFileF1);
	SG_FILE_NULLCLOSE(pCtx, pFileF2);
	SG_FILE_NULLCLOSE(pCtx, pFileF3);
}