static int cp_export( char const *fname ) { #define CLEANUP if(dest) dest->api->finalize(dest); if(fdev) fdev->api->finalize(fdev) whio_dev * fdev = whefs_dev_open( WHEFSApp.fs, fname, false ); if( ! fdev ) { APPERR("Could not open pseudo-file '%s' for reading!\n",fname); return ErrOpenFailed; } whio_dev * dest = whio_dev_for_filename( fname, "w" ); if( ! dest ) { APPERR("Could not local file '%s' for writing!\n",fname); CLEANUP; return ErrOpenFailed; } dest->api->truncate( dest, 0U ); const size_t destSize = whio_dev_size( fdev ); /* it makes me sick to think of how many disk accesses that needs. */ unsigned char buf[WHEFS_CP_BUFFER_SIZE]; size_t wrc = 0; size_t total = 0; while( true ) { size_t rdrc = fdev->api->read( fdev, buf, WHEFS_CP_BUFFER_SIZE ); //WHEFS_DBG("Read %u of %u bytes.", rdrc, WHEFS_CP_BUFFER_SIZE ); if( ! rdrc ) break; wrc = dest->api->write( dest, buf, rdrc ); //WHEFS_DBG("Wrote %u of %u bytes.", wrc, rdrc ); if( wrc != rdrc ) { APPERR("Write failed! Read %u-byte block but could only write %u bytes to '%s'!\n", rdrc, wrc, fname ); CLEANUP; return ErrIO; } total += wrc; if( wrc < WHEFS_CP_BUFFER_SIZE ) break; } if( total != destSize ) { APPERR("Could only write %u of %u bytes!\n", total, destSize ); CLEANUP; return ErrIO; } VERBOSE("Copied %u bytes from EFS into [%s].\n",total, fname); CLEANUP; #undef CLEANUP return 0; }
static int cp_import( char const *fname ) { #define CLEANUP if(inf) inf->finalize(inf); whio_dev * inf = whio_dev_for_filename( fname, "r" ); if( ! inf ) { APPERR("Could not open local file '%s' for reading!\n",fname); return ErrOpenFailed; } int rc = whefs_import_dev( WHEFSApp.fs, inf, fname, true ); size_t sz = whio_dev_size( inf ); inf->api->finalize(inf); if( rc != whefs_rc.OK ) { APPERR("Import of file [%s] failed!\n", fname ); return rc; } VERBOSE("Copied %u bytes from [%s] into EFS\n", sz, fname); #undef CLEANUP return 0; }
int whefs_test_insert_dummy_files( whefs_fs * fs ) { int rc = whefs_rc.OK; whefs_file * F = 0; whefs_file_stats st; size_t nid = 0; char const * fname = "test_file_number_1"; size_t szrc = 0; whefs_inode ino; whio_dev * dev = 0; size_t i = 0; size_t total = 0; if( ! fs || ! fs->dev ) return whefs_rc.ArgError; #define INSERT(FN) \ fname = FN; \ F = whefs_fopen( fs, FN, "r+" ); \ assert( F && "whefs_fopen() failed!"); \ nid = F->inode; \ szrc = whefs_fwrite( F, 3, 1, "hi!" ); \ WHEFS_DBG("fwrite result=%u",szrc); \ rc = whefs_fstat( F, &st ); \ WHEFS_DBG("fstat rc=%d\t F->inode = %u\tF->bytes = %u\tF->blocks = %u", rc, st.inode, st.bytes, st.blocks ); \ rc = whefs_fclose( F ); \ assert( (whefs_rc.OK == rc) && "whefs_fclose() failed!" ); \ F = 0; INSERT("test_file_number_1"); INSERT("test_file_number_2"); #undef INSERT #if 1 whefs_inode_id_read( fs, nid, &ino ); whefs_inode_name_set( fs, ino.id, "will be renamed"); /*whefs_inode_save( fs, &ino ); */ dev = whefs_dev_for_inode( fs, ino.id, true ); WHEFS_DBG("dev=%p",(void const *)dev); assert( dev && "opening of device for inode failed!" ); nid = dev->api->write( dev, "Watson, come here!", 18 ); WHEFS_DBG("write rc=%u", nid ); nid = dev->api->write( dev, "\nComing, Alexander!", 19 ); WHEFS_DBG("write rc=%u", nid ); dev->api->finalize(dev); #endif #if 1 /*whefs_inode_next_free( fs, &ino, true ); */ /*ino = whefs_inode_empty; ino.id = nid; */ whefs_inode_id_read( fs, ino.id, &ino ); WHEFS_DBG("Trampling over inode #%u", ino.id ); fname = "via whio_dev_inode"; whefs_inode_name_set( fs, ino.id, fname ); dev = whefs_dev_for_inode( fs, ino.id, true ); WHEFS_DBG("dev=%p",(void const *)dev); assert( dev && "couldn't re-open device!"); dev->api->flush(dev); assert( dev && "opening of device for inode failed!" ); for( ; i < 10; ++i ) { nid = whio_dev_writef( dev, "Test #%02u", i ); total += nid; } WHEFS_DBG("dev size=%u", whio_dev_size(dev) ); dev->api->truncate( dev, 0 ); dev->api->seek( dev, 30, SEEK_SET ); WHEFS_DBG("dev size=%u", whio_dev_size(dev) ); nid = dev->api->write( dev, "Stop saying that!!", 18 ); total += nid; WHEFS_DBG("dev size=%u", whio_dev_size(dev) ); dev->api->finalize(dev); F = whefs_fopen( fs, fname, "r+" ); assert( F && "re-open of inode failed!" ); dev = whefs_fdev( F ); { char const * str = "...And now a final word."; size_t slen = strlen(str); size_t dsize = whefs_fseek( F, 0, SEEK_END ); WHEFS_DBG("F size=%u, slen=%u", dsize, slen ); nid = whefs_fwrite( F, slen, 1, str ); /*WHEFS_DBG("whefs_fwrite() rc=%u", nid ); */ assert( (1 == nid) && "write failed!" ); dev->api->seek( dev, dsize + slen + 10, SEEK_SET ); dev->api->write( dev, "!", 1 ); /*nid = whefs_fwrite( F, 1, 1, "!" ); */ WHEFS_DBG("dev size=%u", whio_dev_size(dev) ); } whefs_fclose( F ); #endif return rc; }
int whefs_import_dev( whefs_fs * fs, whio_dev * src, char const * fname, bool overwrite ) { int rc = whefs_rc.OK; whefs_inode ino = whefs_inode_empty; bool existed = false; whio_dev * imp; whio_size_t oldPos, szrc; size_t oldFSize, newFSize; if( ! fs || !src || !fname || !*fname ) return whefs_rc.ArgError; rc = whefs_inode_by_name( fs, fname, &ino ); if( rc == whefs_rc.OK ) { if( ! overwrite ) return whefs_rc.AccessError; existed = true; } else { rc = whefs_inode_next_free( fs, &ino, true ); if( whefs_rc.OK != rc ) return rc; rc = whefs_inode_name_set( fs, ino.id, fname ); if( whefs_rc.OK != rc ) return rc; whefs_inode_flush( fs, &ino ); } imp = whefs_dev_for_inode( fs, ino.id, true ); if( ! imp ) return whefs_rc.InternalError; oldPos = src->api->tell( src ); szrc = src->api->seek( src, 0, SEEK_SET ); if( whio_rc.SizeTError == szrc ) { imp->api->finalize( imp ); if( ! existed ) { whefs_inode_unlink( fs, &ino ); } return whefs_rc.RangeError; } oldFSize = ino.data_size; newFSize = whio_dev_size( src ); rc = imp->api->truncate( imp, newFSize ); if( rc != whefs_rc.OK ) { WHEFS_DBG_ERR("Could not truncate '%s' to %u bytes!", fname, newFSize ); imp->api->truncate( imp, oldFSize ); src->api->seek( src, oldPos, SEEK_SET ); imp->api->finalize( imp ); if( ! existed ) { whefs_inode_unlink( fs, &ino ); } return rc; } imp->api->flush( imp ); if( 0 == newFSize ) { /*WHEFS_DBG("Importing 0-byte file."); */ src->api->seek( src, oldPos, SEEK_SET ); imp->api->finalize(imp); return whefs_rc.OK; } else { enum { bufSize = 1024 * 8 }; unsigned char buf[bufSize]; size_t impSize; size_t wlen = newFSize; size_t totalR = 0; size_t totalW = 0; size_t rrc = 0; size_t wrc = 0; memset( buf, 0, bufSize ); imp->api->seek( imp, 0, SEEK_SET ); do { rrc = src->api->read( src, buf, bufSize ); totalR += rrc; if( ! rrc ) break; if( (wlen - rrc) > wlen ) { WHEFS_DBG_ERR("Read an unexpected length (%u)! Continuing would cause an underflow!", rrc); break; } wlen -= rrc; wrc = imp->api->write( imp, buf, rrc ); /*WHEFS_DBG("wrc=%u, rrc=%u, xoimp->tell=%u",wrc, rrc, imp->api->tell(imp)); */ totalW += wrc; if( wrc != rrc ) break; } while( rrc && wrc ); src->api->seek( src, oldPos, SEEK_SET ); impSize = whio_dev_size( imp ); imp->api->finalize(imp); imp = 0; rc = whefs_rc.OK; if( totalR != totalW ) { WHEFS_DBG_ERR("Pseudofile [%s]: Total read bytes (%u) != total written bytes (%u)", fname, totalR, totalW ); rc = whefs_rc.IOError; } else if( impSize != newFSize ) { WHEFS_DBG_ERR("Pseudofile [%s]: Imported file size (%u) does not match the source's size (%u)", fname, totalR, totalW ); rc = whefs_rc.IOError; } if( whefs_rc.OK != rc ) { if( ! existed ) { whefs_inode_unlink( fs, &ino ); } } return rc; } }