+/**
+ * Write a full block of data.
+ */
+static int write_block(int fd,const char *buf,size_t size) {
+ size_t orig = size;
+ while ( size > 0 ) {
+ ssize_t n = write( fd, buf, size );
+ if ( n <= 0 ) {
+ return n;
+ }
+ buf += n;
+ size -= n;
+ }
+ return orig;
+}
+
+static int fusefile_write_buf(const char *path, struct fuse_bufvec *buf,
+ off_t off, struct fuse_file_info *fi) {
+#if DEBUG
+ fprintf( stderr, "fusefile_write_buf( %s )\n", path );
+#endif
+ if ( strcmp( path, "/" ) != 0 ) {
+ return -ENOENT;
+ }
+
+ // Ensure a pad was nominated
+ if ( pad.filename == 0 ) {
+ return 1;
+ }
+
+ // Determine total size
+ size_t size = 0;
+ int i;
+#if DEBUG
+ fprintf( stderr, "count = %ld\n", buf->count );
+#endif
+ for ( i = 0; i < buf->count; i++ ) {
+ struct fuse_buf *p = &buf->buf[ i ];
+ size += p->size;
+ }
+ static char meta[ 100 ];
+ sprintf( meta, "%ld\n%ld\n", off, size );
+#if DEBUG
+ fprintf( stderr, "meta( %ld %ld )\n", off, size );
+#endif
+ if ( write_block( pad.fd, meta, strlen( meta ) ) <= 0 ) {
+ perror( pad.filename );
+ return -EIO;
+ }
+ struct Source source = {
+ .filename = pad.filename,
+ .fd = pad.fd,
+ .from = lseek( pad.fd, 0, SEEK_END ),
+ .to = 0,
+ .start = 0
+ };
+ for ( i = 0; i < buf->count; i++ ) {
+ struct fuse_buf *p = &buf->buf[i];
+ if ( p->flags & FUSE_BUF_IS_FD ) {
+#if DEBUG
+ fprintf( stderr, "Content held in a file ... HELP!!\n" );
+#endif
+ return -EIO;
+ } else {
+ ssize_t n = write_block( pad.fd, (char*) p->mem, p->size );
+ if ( n != p->size ) {
+ return -EIO;
+ }
+ }
+ }
+ source.to = source.from + size;
+ insert_source( &source, off );
+ times.mtime = time( 0 );
+ return size;
+}
+
+/**
+ * Insert a fragment at <off>. The data is appended to the pad file,
+ * and a descriptor is inserted; the fragment containing <off> is
+ * first split, unless <off> is at its start, and then new fragment
+ * descriptor is inserted.
+ */
+static int fusefile_write(const char *path, const char *buf, size_t size,
+ off_t off, struct fuse_file_info *fi)
+{
+#if DEBUG
+ fprintf( stderr, "fusefile_write( %s %ld )\n", path, size );
+#endif
+ if ( strcmp( path, "/" ) != 0 ) {
+ return -ENOENT;
+ }
+
+ // Ensure a pad was nominated
+ if ( pad.filename == 0 ) {
+ return 1;
+ }
+ static char meta[ 100 ];
+ sprintf( meta, "%ld\n%ld\n", off, size );
+ if ( write_block( pad.fd, meta, strlen( meta ) ) <= 0 ) {
+ perror( pad.filename );
+ return -EIO;
+ }
+ struct Source source = {
+ .filename = pad.filename,
+ .fd = pad.fd,
+ .from = lseek( pad.fd, 0, SEEK_END ),
+ .to = 0,
+ .start = 0
+ };
+ ssize_t n = write_block( pad.fd, buf, size );
+ if ( n != size ) {
+ return n;
+ }
+ source.to = source.from + size;
+ insert_source( &source, off );
+ times.mtime = time( 0 );
+ return size;
+}
+