void SG_workingdir__generate_and_create_temp_dir_for_purpose(SG_context * pCtx, const SG_pathname * pPathWorkingDirectoryTop, const char * pszPurpose, SG_pathname ** ppPathTempDir) { SG_pathname * pPathTempRoot = NULL; SG_pathname * pPath = NULL; SG_string * pString = NULL; SG_int64 iTimeUTC; SG_time tmLocal; SG_uint32 kAttempt = 0; SG_NONEMPTYCHECK_RETURN(pszPurpose); SG_NULLARGCHECK_RETURN(ppPathTempDir); // get path to "<wd-top>/.sgtemp". SG_ERR_CHECK( SG_workingdir__get_temp_path(pCtx,pPathWorkingDirectoryTop,&pPathTempRoot) ); SG_ERR_CHECK( SG_time__get_milliseconds_since_1970_utc(pCtx,&iTimeUTC) ); SG_ERR_CHECK( SG_time__decode__local(pCtx,iTimeUTC,&tmLocal) ); SG_ERR_CHECK( SG_STRING__ALLOC(pCtx,&pString) ); while (1) { // build path "<wd-top>/.sgtemp/<purpose>_20091201_0". // where <purpose> is something like "revert" or "merge". SG_ERR_CHECK( SG_string__sprintf(pCtx,pString,"%s_%04d%02d%02d_%d", pszPurpose, tmLocal.year,tmLocal.month,tmLocal.mday, kAttempt++) ); SG_ERR_CHECK( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx,&pPath,pPathTempRoot,SG_string__sz(pString)) ); // try to create a NEW temp directory. if this path already exists on disk, // loop and try again. if we have a hard errors, just give up. SG_fsobj__mkdir_recursive__pathname(pCtx,pPath); if (SG_context__has_err(pCtx) == SG_FALSE) goto success; if (SG_context__err_equals(pCtx,SG_ERR_DIR_ALREADY_EXISTS) == SG_FALSE) SG_ERR_RETHROW; SG_context__err_reset(pCtx); SG_PATHNAME_NULLFREE(pCtx,pPath); } success: *ppPathTempDir = pPath; SG_STRING_NULLFREE(pCtx, pString); SG_PATHNAME_NULLFREE(pCtx, pPathTempRoot); return; fail: SG_STRING_NULLFREE(pCtx, pString); SG_PATHNAME_NULLFREE(pCtx, pPathTempRoot); SG_PATHNAME_NULLFREE(pCtx, pPath); }
/** * Create a per-tx temp-dir if we don't already have one. * */ void sg_wc_tx__create_session_temp_dir(SG_context * pCtx, SG_wc_tx * pWcTx) { char bufTidSession[SG_TID_MAX_BUFFER_LENGTH]; SG_uint32 nrDigits = 10; if (pWcTx->pPathSessionTempDir) return; // pick a space in /tmp for exporting temporary copies of the files // so that internal and/or external tools can compare them. // // TODO 2012/05/02 Investigate the use of SG_workingdir__get_temp_path() (which // TODO creates things in .sgdrawer rather than /tmp). // TODO (see also sg_mrg__private_file_mrg.h) // TODO See also sg_vv2__diff__create_session_temp_dir(). SG_ERR_CHECK( SG_PATHNAME__ALLOC__USER_TEMP_DIRECTORY(pCtx, &pWcTx->pPathSessionTempDir) ); SG_ERR_CHECK( SG_tid__generate2(pCtx, bufTidSession, sizeof(bufTidSession), nrDigits) ); SG_ERR_CHECK( SG_pathname__append__from_sz(pCtx, pWcTx->pPathSessionTempDir, bufTidSession) ); SG_ERR_TRY( SG_fsobj__mkdir_recursive__pathname(pCtx, pWcTx->pPathSessionTempDir) ); SG_ERR_CATCH_IGNORE( SG_ERR_DIR_ALREADY_EXISTS ); SG_ERR_CATCH_END; #if 0 && defined(DEBUG) SG_ERR_IGNORE( SG_console(pCtx, SG_CS_STDERR, "CreateSessionTempDir: %s\n", SG_pathname__sz(pWcTx->pPathSessionTempDir)) ); #endif fail: return; }
void MyFn(create_tmp_src_dir)(SG_context * pCtx, SG_pathname ** ppPathnameTempDir) { // create a temp directory in the current directory to be the // home of some userfiles. // caller must free returned value. SG_pathname * pPathnameTempDir = NULL; VERIFY_ERR_CHECK( unittest__alloc_unique_pathname_in_cwd(pCtx,&pPathnameTempDir) ); VERIFY_ERR_CHECK( SG_fsobj__mkdir_recursive__pathname(pCtx, pPathnameTempDir) ); INFOP("mktmpdir",("Temp Src Dir is [%s]",SG_pathname__sz(pPathnameTempDir))); *ppPathnameTempDir = pPathnameTempDir; return; fail: SG_PATHNAME_NULLFREE(pCtx, pPathnameTempDir); }
/** * 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); }
void u0020_utf8pathnames__mkdir_tmp_dir(SG_context * pCtx, SG_pathname ** ppPathnameTmpDir) { // create a temporary directory using a random name in the // current directory or in TMP. // // return the name of the pathname. char bufTid[SG_TID_MAX_BUFFER_LENGTH]; SG_pathname * pPathnameTmpDir = NULL; VERIFY_ERR_CHECK( SG_tid__generate2(pCtx, bufTid, sizeof(bufTid), 32) ); VERIFY_ERR_CHECK( SG_PATHNAME__ALLOC__USER_TEMP_DIRECTORY(pCtx, &pPathnameTmpDir) ); VERIFY_ERR_CHECK( SG_pathname__append__from_sz(pCtx, pPathnameTmpDir,bufTid) ); VERIFY_ERR_CHECK( SG_fsobj__mkdir_recursive__pathname(pCtx, pPathnameTmpDir) ); *ppPathnameTmpDir = pPathnameTmpDir; return; fail: SG_PATHNAME_NULLFREE(pCtx, pPathnameTmpDir); }
/** * 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); }