X-Git-Url: https://git.rrq.au/?a=blobdiff_plain;f=fusefile.c;h=5a51066232251a3db09dc310df5abdd4fbb6c043;hb=b33bccec9aef7758588edfb92a46bdd835c730f7;hp=476ca9d8fb1ffa847e094150b44223a816ed7603;hpb=d7e225ba17002eec13f528e33fe4fc7c54788388;p=rrq%2Ffusefile.git diff --git a/fusefile.c b/fusefile.c index 476ca9d..5a51066 100644 --- a/fusefile.c +++ b/fusefile.c @@ -61,49 +61,10 @@ static void print_source(struct Source *p) { } #endif -// Scan the source specification, and return the length of the -// inclusion. "filename/from,to" -// filename -// filename/from -// filename/-to -// filename/from-to -static size_t scan_source(char *in,struct Source *p) { - int e = strlen( in ); - int i = e-1; - int s = -1; - int m = -1; - // scan for last '/' and last '-' - for ( ; i >= 0; i-- ) { - if ( in[i] == '/' ) { - s = i; - break; - } - if ( in[i] == '-' ) { - m = i; - } - } -#if DEBUG - fprintf( stderr, "m=%d s=%d\n", m, s ); -#endif - // Copy the filename, and set from and to - p->filename = strndup( in, ( s < 0 )? e : s ); - struct stat buf; - if ( stat( p->filename, & buf ) ) { - perror( p->filename ); - return 1; - } - p->from = ( s < 0 )? 0 : atol( in+s+1 ); - if ( p->from < 0 ) { - p->from = 0; - } -#if DEBUG - fprintf( stderr, "p->from=%ld\n", p->from ); -#endif - p->to = ( m < 0 )? buf.st_size : atol( in+m+1 ); - if ( p->from > p->to || p->to > buf.st_size ) { - return 1; - } - return 0; +static char *range; +static unsigned int c; +static int RANGE(int SCAN,int N ) { + return ( SCAN == N ) && *(range+c) == 0; } static int setup_sources(char **argv,int i,int n) { @@ -115,22 +76,56 @@ static int setup_sources(char **argv,int i,int n) { int j = 0; sources.size = 0; for ( ; j < n; i++, j++ ) { + struct stat filestat; struct Source *p = sources.array + j; - if ( scan_source( argv[i], p ) ) { - // should free everything malloc-ed - return 1; - } - p->start = sources.size; - sources.size += p->to - p->from; + // Open the fragment file rw if possible, else ro + range = strrchr( argv[i], '/' ); // last '/' + p->filename = range? strndup( argv[i], range - argv[i] ) : argv[i]; p->fd = open( p->filename, O_RDWR ); + int rdonly = 0; if ( p->fd < 0 ) { - fprintf( stderr, "** %s opened read-only\n", p->filename ); + rdonly = 1; p->fd = open( p->filename, O_RDONLY ); } if ( p->fd < 0 ) { perror( p->filename ); - return 1; + return 1; // Error return + } + if ( stat( p->filename, &filestat ) ) { + perror( p->filename ); + return 1; + } + if ( rdonly ) { + fprintf( stderr, "** %s opened read-only\n", p->filename ); + } + p->from = 0; + p->to = filestat.st_size; + // Process any range variation + if ( range && *(++range) ) { + unsigned int a,b; + if ( RANGE( sscanf( range, "%u-%u%n", &a, &b, &c ), 2 ) ) { + p->from = a; + p->to = b; + } else if ( RANGE( sscanf( range, "%u--%u%n", &a, &b, &c ), 2 ) ) { + p->from = a; + p->to -= b; + } else if ( RANGE( sscanf( range, "%u-%n", &a, &c ), 1 ) ) { + p->from = a; + } else if ( RANGE( sscanf( range, "%u%n", &a, &c ), 1 ) ) { + p->from = a; + } else if ( RANGE( sscanf( range, "-%u%n", &b, &c ), 1 ) ) { + p->to = b; + } else if ( RANGE( sscanf( range, "--%u%n", &b, &c ), 1 ) ) { + p->to -= b; + } else if ( RANGE( sscanf( range, "-%n", &c), 0 ) ) { + // Acceptable as "start-end" range + } else { + fprintf( stderr, "** BAD RANGE: %s\n", argv[i] ); + return 1; + } } + p->start = sources.size; // the fusefile position of fragment + sources.size += p->to - p->from; #if DEBUG print_source( p ); #endif @@ -217,7 +212,7 @@ static int fusefile_read(const char *path, char *buf, size_t size, #endif int i = find_source( off ); if ( i < 0 ) { - return ( off == sources.size )? 0 : -ENOENT; + return ( off == sources.size )? rr : -ENOENT; } if ( sources.array[i].fd < 0 ) { return -ENOENT; @@ -225,6 +220,7 @@ static int fusefile_read(const char *path, char *buf, size_t size, #if DEBUG print_source( &sources.array[i] ); #endif + times.atime = time( 0 ); size_t b = off - sources.array[i].start + sources.array[i].from; size_t n = sources.array[i].to - b; if ( n > size ) { @@ -252,10 +248,28 @@ static int fusefile_read(const char *path, char *buf, size_t size, off += r; size -= r; } - times.atime = time( 0 ); return rr; } +/** + * Poll for IO readiness. + */ +int fusefile_poll(const char *path, struct fuse_file_info *fi, + struct fuse_pollhandle *ph, unsigned *reventsp ) +{ +#if DEBUG + fprintf( stderr, "fusefile_poll( %s ) %p %d\n", path, ph, *reventsp ); +#endif + if( strcmp( path, "/" ) != 0 ) { + return -ENOENT; + } + if ( ph ) { + return fuse_notify_poll( ph ); + } + return 0; +} + + /** * Write a full block of data over the sources at the offset */ @@ -269,8 +283,8 @@ static int write_block(off_t off,const char *buf,size_t size) { return -EIO; // past EOF } struct Source *source = &sources.array[ index ]; - off_t from = off - source->start; - off_t max = source->to - source->from - from; + off_t from = off - source->start + source->from; + off_t max = source->to - from; if ( lseek( source->fd, from, SEEK_SET ) < 0 ) { return -EIO; } @@ -392,11 +406,25 @@ static int fusefile_truncate(const char *path, off_t len) { return -EIO; } +void *fusefile_init(struct fuse_conn_info *fci) { +#if DEBUG + fprintf( stderr, "fusefile_init( %d, %d )\n", fci->async_read, fci->want ); +#endif + // Disable asynchronous reading + fci->async_read = 0; + fci->want &= ~FUSE_CAP_ASYNC_READ; +#if DEBUG + fprintf( stderr, "fusefile_init( %d, %d )\n", fci->async_read, fci->want ); +#endif + return 0; +} + static struct fuse_operations fusefile_oper = { .getattr = fusefile_getattr, .chmod = fusefile_chmod, .open = fusefile_open, .read = fusefile_read, + .poll = fusefile_poll, .write = fusefile_write, .write_buf = fusefile_write_buf, .destroy = fusefile_destroy, @@ -406,7 +434,7 @@ static struct fuse_operations fusefile_oper = { .truncate = fusefile_truncate, //.truncate = fusefile_truncate, //.release = fusefile_release, - //void *(*init) (struct fuse_conn_info *conn); + .init = fusefile_init, }; static void usage() { @@ -420,28 +448,31 @@ static void usage() { /** * Set up the arguments for the fuse_main call, adding our own. + * argv[argc] is the mount point argument */ static int setup_argv(int argc,char ***argv) { + // note: (*argv)[ argc ] is the mount point argument char *OURS[] = { "-odefault_permissions", - (*argv)[ --argc ] // note: (*argv)[ argc-1 ] = the mount point + (*argv)[ argc ] }; #define OURSN ( sizeof( OURS ) / sizeof( char* ) ) - int N = argc + OURSN; // new argv-tobe size, excluding null - char **out = malloc( ( N + 1 ) * sizeof( char* ) ); + int N = argc + OURSN; + // Allocate new arg array plus terminating null pointer + char **out = malloc( ( N + 1 ) * sizeof( char* ) ); int i; for ( i = 0; i < argc; i++ ) { out[ i ] = (*argv)[i]; - fprintf( stderr, " %s", out[ i ] ); + //fprintf( stderr, " %s", out[ i ] ); } for ( i = 0; i < OURSN; i++ ) { out[ argc + i ] = OURS[i]; - fprintf( stderr, " %s", out[ i ] ); + //fprintf( stderr, " %s", out[ i ] ); } out[ N ] = 0; - fprintf( stderr, "\n" ); + //fprintf( stderr, "\n" ); (*argv) = out; - return N; + return N; // Don't include the terminating null pointer } /** @@ -466,8 +497,8 @@ int main(int argc, char *argv[]) if ( i > argc - 2 ) { // At least mount point plus one source usage(); } - mnt = argv[ i++ ]; // First non-option argument is the mount pount fuseargc = i; + mnt = argv[ i++ ]; // First non-option argument is the mount pount if ( setup_sources( argv, i, argc-i ) ) { return 1; }