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); }
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); }
static void _write_file_chunk(SG_context* pCtx, SG_curl* pCurl, char* buffer, SG_uint32 bufLen, void* pVoidState, SG_uint32* pLenHandled) { SG_file* pFile = (SG_file*)pVoidState; SG_ERR_CHECK_RETURN( _check_for_and_handle_json_500(pCtx, pCurl, buffer, bufLen) ); if (bufLen) // libcurl docs say we may be called with zero length if file is empty SG_ERR_CHECK_RETURN( SG_file__write(pCtx, pFile, bufLen, (SG_byte*)buffer, pLenHandled) ); }
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); }
void SG_random__write_random_bytes_to_file(SG_context * pCtx, SG_file * pFile, SG_uint64 numBytes) { SG_byte buffer[1024]; SG_NULLARGCHECK_RETURN(pFile); while(numBytes>=1024) { SG_random_bytes(buffer, 1024); SG_ERR_CHECK( SG_file__write(pCtx, pFile, 1024, buffer, NULL) ); numBytes-=1024; } if(numBytes>0) { SG_random_bytes(buffer, (SG_uint32)numBytes); SG_ERR_CHECK( SG_file__write(pCtx, pFile, (SG_uint32)numBytes, buffer, NULL) ); numBytes-=numBytes; } fail: ; }
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); }
static void read_entire_stream__file( SG_context* pCtx, CFReadStreamRef myReadStream, SG_pathname* pPath, CFHTTPMessageRef* pp, SG_bool b_progress ) { CFHTTPMessageRef myResponse = NULL; CFIndex numBytesRead = 0; SG_file* pFile = NULL; SG_int64 content_length = 0; SG_int64 so_far = 0; SG_ERR_CHECK( SG_file__open__pathname(pCtx, pPath, SG_FILE_CREATE_NEW | SG_FILE_WRONLY, 0644, &pFile) ); do { UInt8 buf[8192]; // TODO numBytesRead = CFReadStreamRead(myReadStream, buf, sizeof(buf)); if( numBytesRead > 0 ) { SG_ERR_CHECK( SG_file__write(pCtx, pFile, numBytesRead, buf, NULL) ); if (!myResponse) { myResponse = (CFHTTPMessageRef)CFReadStreamCopyProperty(myReadStream, kCFStreamPropertyHTTPResponseHeader); CFStringRef contentLengthString = CFHTTPMessageCopyHeaderFieldValue(myResponse, CFSTR("Content-Length")); if (contentLengthString) { // TODO 32 bit limit problem here content_length = CFStringGetIntValue(contentLengthString); CFRelease(contentLengthString); } if (b_progress) { SG_ERR_CHECK( SG_log__set_steps(pCtx, content_length / 1024, "KB") ); } } so_far += (SG_uint32) numBytesRead; if (b_progress) { SG_ERR_CHECK( SG_log__set_finished(pCtx, so_far / 1024) ); } } else if( numBytesRead < 0 ) { CFStreamError myErr = CFReadStreamGetError(myReadStream); // TODO clean this up if (myErr.domain == kCFStreamErrorDomainPOSIX) { if (ETIMEDOUT == myErr.error) { usleep(5000); numBytesRead = 0; } else { // Interpret myErr.error as a UNIX errno. SG_ERR_THROW( SG_ERR_ERRNO(myErr.error) ); } } else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) { // Interpret myErr.error as a MacOS error code. // TODO SG_ERR_THROW( SG_ERR_MAC((OSStatus) myErr.error) ); SG_ERR_THROW( SG_ERR_UNSPECIFIED ); } } } while( numBytesRead > 0 ); SG_ERR_CHECK( SG_file__close(pCtx, &pFile) ); if (!myResponse) { myResponse = (CFHTTPMessageRef)CFReadStreamCopyProperty(myReadStream, kCFStreamPropertyHTTPResponseHeader); } *pp = myResponse; myResponse = NULL; fail: if (pFile) { SG_ERR_CHECK( SG_file__close(pCtx, &pFile) ); // TODO delete it too } if (myResponse) { CFRelease(myResponse); } }
void MyFn(create_blob_from_file)(SG_context * pCtx, SG_repo * pRepo, const SG_pathname * pPathnameTempDir, SG_uint64 lenFile, const char * szSrc) { // create a file of length "lenFile" in the temp directory. // use it to create a blob. // try to create it a second time and verify that we get an duplicate-hid error. char* pszidGidRandom1 = NULL; char* pszidGidRandom2 = NULL; SG_pathname * pPathnameTempFile1 = NULL; SG_pathname * pPathnameTempFile2 = NULL; SG_file * pFileTempFile1 = NULL; SG_file * pFileTempFile2 = NULL; SG_uint32 lenSrc; SG_uint64 lenWritten; char* pszidHidBlob1 = NULL; char* pszidHidBlob1Dup = NULL; char* pszidHidBlob2 = NULL; char* pszidHidVerify1 = NULL; char* pszidHidVerify2 = NULL; SG_bool bEqual; SG_repo_tx_handle* pTx = NULL; SG_uint64 iBlobFullLength = 0; ////////////////////////////////////////////////////////////////// // create temp-file-1 of length "lenFile" in the temp directory. VERIFY_ERR_CHECK_DISCARD( SG_gid__alloc(pCtx, &pszidGidRandom1) ); VERIFY_ERR_CHECK_DISCARD( SG_gid__alloc(pCtx, &pszidGidRandom2) ); VERIFY_ERR_CHECK_DISCARD( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPathnameTempFile1,pPathnameTempDir,(pszidGidRandom1)) ); VERIFY_ERR_CHECK_DISCARD( SG_file__open__pathname(pCtx, pPathnameTempFile1,SG_FILE_RDWR|SG_FILE_CREATE_NEW,0644,&pFileTempFile1) ); // write random gid at the beginning of the file // so that we won't get collisions if we are called // multiple times. VERIFY_ERR_CHECK_DISCARD( SG_file__write(pCtx, pFileTempFile1,(SG_uint32)strlen(pszidGidRandom1),(SG_byte *)pszidGidRandom1,NULL) ); VERIFY_ERR_CHECK_DISCARD( SG_file__write(pCtx, pFileTempFile1,1,(SG_byte *)"\n",NULL) ); // generate lots of data in the file so that we'll cause the // blob routines to exercise the chunking stuff. lenSrc = (SG_uint32)strlen(szSrc); lenWritten = 0; while (lenWritten < lenFile) { VERIFY_ERR_CHECK_DISCARD( SG_file__write(pCtx, pFileTempFile1,lenSrc,(SG_byte *)szSrc,NULL) ); lenWritten += lenSrc; } // the test file does NOT have a final LF. i'm not sure it matters one way or the // other, but i'm just saying that we're not putting on a final LF. SG_ERR_IGNORE( SG_file__seek(pCtx, pFileTempFile1,0) ); ////////////////////////////////////////////////////////////////// // use currently open temp file to create a blob. // we get the HID back. (we need to free it later.) VERIFY_ERR_CHECK_DISCARD( SG_repo__begin_tx(pCtx, pRepo, &pTx) ); VERIFY_ERR_CHECK_DISCARD( SG_repo__store_blob_from_file(pCtx, pRepo,pTx,NULL,SG_FALSE,pFileTempFile1,&pszidHidBlob1,&iBlobFullLength) ); VERIFY_ERR_CHECK_DISCARD( SG_repo__commit_tx(pCtx, pRepo, &pTx) ); INFOP("create_blob_from_file",("Created blob [%s]",(pszidHidBlob1))); ////////////////////////////////////////////////////////////////// // try to create blob again and verify we get an duplicate-hid error. // Ian TODO: Put this back when SG_ERR_BLOBFILEALREADYEXISTS has been replaced. // VERIFY_ERR_CHECK_DISCARD( SG_repo__begin_tx(pCtx, pRepo, &pTx) ); // err = SG_repo__store_blob_from_file(pRepo,pTx,SG_FALSE,pFileTempFile1,&pszidHidBlob1Dup); // VERIFYP_CTX_ERR_IS("create_blob_from_file(duplicate)", pCtx, SG_ERR_BLOBFILEALREADYEXISTS, ("Duplicate create failed [%s][%s]",pszidHidBlob1,pszidHidBlob1Dup)); // VERIFY_ERR_CHECK_DISCARD( SG_repo__commit_tx(pCtx, pRepo, SG_DAGNUM__NONE, NULL, &pTx) ); ////////////////////////////////////////////////////////////////// // create empty temp-file-2 and try to read the blob from the repo. VERIFY_ERR_CHECK_DISCARD( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPathnameTempFile2,pPathnameTempDir,(pszidGidRandom2)) ); VERIFY_ERR_CHECK_DISCARD( SG_file__open__pathname(pCtx, pPathnameTempFile2,SG_FILE_RDWR|SG_FILE_CREATE_NEW,0644,&pFileTempFile2) ); VERIFY_ERR_CHECK_DISCARD( SG_repo__fetch_blob_into_file(pCtx, pRepo,pszidHidBlob1,pFileTempFile2,NULL) ); ////////////////////////////////////////////////////////////////// // verify that the contents of temp-file-2 is identical to the // contents of temp-file-1. (we already know that the HIDs match // and was verified during the fetch, but there are times when the // HID is just being used as a key -- it doesn't mean that what we // actually restored is correct. VERIFY_ERR_CHECK_DISCARD( SG_repo__alloc_compute_hash__from_file(pCtx, pRepo, pFileTempFile1, &pszidHidVerify1) ); VERIFY_ERR_CHECK_DISCARD( SG_repo__alloc_compute_hash__from_file(pCtx, pRepo, pFileTempFile2, &pszidHidVerify2) ); bEqual = (0 == (strcmp(pszidHidVerify1,pszidHidVerify2))); VERIFY_COND("create_blob_from_file(verify v1==v2)",bEqual); bEqual = (0 == (strcmp(pszidHidVerify1,pszidHidBlob1))); VERIFY_COND("create_blob_from_file(verify v1==id)",bEqual); ////////////////////////////////////////////////////////////////// // TODO delete temp source file SG_ERR_IGNORE( SG_file__close(pCtx, &pFileTempFile1) ); SG_ERR_IGNORE( SG_file__close(pCtx, &pFileTempFile2) ); ////////////////////////////////////////////////////////////////// // cleanup SG_NULLFREE(pCtx, pszidGidRandom1); SG_NULLFREE(pCtx, pszidGidRandom2); SG_NULLFREE(pCtx, pszidHidBlob1); SG_NULLFREE(pCtx, pszidHidBlob1Dup); SG_NULLFREE(pCtx, pszidHidBlob2); SG_NULLFREE(pCtx, pszidHidVerify1); SG_NULLFREE(pCtx, pszidHidVerify2); SG_PATHNAME_NULLFREE(pCtx, pPathnameTempFile1); SG_PATHNAME_NULLFREE(pCtx, pPathnameTempFile2); }
/** * 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); }