#include #include #include #include #include #include #include #include #include extern int errno; typedef struct list_s { int status; off_t offset; char *name; } list_t; typedef struct get_ret_s { int status; size_t count; char *buffer; } get_ret_t; typedef struct get_param_s { long offset; size_t count; char *name; } get_param_t; char *cred() { static char c[] = "Gustavo Sverzut Barbieri "; return c; } int exist( const char *file ) { struct stat buf; if ( ! file ) return 0; stat( file, &buf ); if ( S_ISREG( buf.st_mode ) ) return 1; return 0; } /** * Return next directory entry. * * Parameter: * dir.name what dir to read * dir.offset where to start reading. * * Return: * Success: * ret.status == 1 * ret.offset > 0 * ret.name != NULL * EOF: * ret.status == 0 * ret.offset == 0 * ret.name == NULL * Error: * ret.status == -errno * ret.offset == 0 * ret.name == NULL */ list_t *list( list_t *dir ) { DIR *d; struct dirent *f; struct stat fstat; int dlen; list_t *ret; errno = 0; assert( dir && dir->name ); ret = (list_t*) calloc( 1, sizeof( list_t ) ); ret->status = 0; ret->offset = 0; ret->name = NULL; if ( ( d = opendir( dir->name ) ) == NULL ) { ret->status = -errno; return ret; } if ( dir->offset ) seekdir( d, dir->offset ); dlen = strlen( dir->name ); while ( ( f = readdir( d ) ) != NULL ) { int len; char *fname; len = strlen( f->d_name ); fname = (char*) malloc( len + dlen + 2 ); strcpy( fname, dir->name ); fname[ dlen ] = '/'; fname[ dlen + 1 ] = '\0'; strcat( fname, f->d_name ); stat( fname, &fstat ); if ( S_ISREG( fstat.st_mode ) ) { ret->name = (char *) malloc( len + dlen + 2 ); strcpy( ret->name, fname ); ret->offset = telldir( d ); ret->status = 1; free( fname ); break; } free( fname ); } closedir( d ); return ret; } /** * Get file piece. * * Parameters: * file.offset where to start reading. * file.count how much to read. * file.name file name to read. * * Return: * Success: * ret.status == 1 * ret.count == file.count * ret.buffer != NULL * EOF: * ret.status == 0 * ret.count < file.count * ret.buffer != NULL * Error: * ret.status == - errno * ret.count == 0 * ret.buffer == NULL */ get_ret_t *get( get_param_t *file ) { FILE *fd = NULL; get_ret_t *ret; errno = 0; assert( file && file->name && file->count ); ret = (get_ret_t*) malloc( sizeof( get_ret_t ) ); ret->status = 0; ret->count = 0; if ( ( fd = fopen( file->name, "r" ) ) == NULL ) { ret->status = - errno; return ret; } ret->buffer = (char *) malloc( file->count ); if ( file->offset ) fseek( fd, file->offset, SEEK_SET ); ret->count = fread( ret->buffer, 1, file->count, fd ); if ( ret->count != file->count ) { if ( feof( fd ) ) ret->status = 0; else if ( ferror( fd ) ) { ret->status = - errno; ret->count = 0; } } else ret->status = 1; fclose( fd ); return ret; } int main( int argc, char *argv[] ) { list_t *file, dir; get_param_t gp; get_ret_t *gr; FILE *fd; printf( "cred='%s'\n", cred() ); printf( "exist( \"%s\" ) = %d (should be 1)\n", argv[0], exist( argv[0] ) ); printf( "exist( \"test123\" ) = %d (should be 0)\n", exist( "test123" ) ); printf( "dir listing:\n" ); dir.offset = 0; dir.name = "."; while ( 1 ) { file = list( &dir ); if ( file->status == 1 ) printf( " file: %s\n", file->name ); else if ( file->status < 0 ) printf( "ERROR: Could not read '%s': %s\n", dir.name, strerror( - file->status ) ); dir.offset = file->offset; free( file->name ); free( file ); if ( dir.offset == 0 ) break; } gp.offset = 0; gp.count = 8000; gp.name = "local"; fd = fopen( "out-test", "w+" ); while ( 1 ) { gr = get( &gp ); if ( gr->status >=0 ) { fwrite( gr->buffer, 1, gr->count, fd ); gp.offset += gr->count; if ( gr->status == 0 ) { free( gr->buffer ); free( gr ); break; } } else { printf( "ERROR: Could not get file '%s': %s\n", gp.name, strerror( - gr->status ) ); free( gr->buffer ); free( gr ); break; } free( gr->buffer ); free( gr ); } fclose( fd ); return 0; } /* author: Gustavo Sverzut Barbieri (http://www.gustavobarbieri.com.br) */