Add --append option to metaflac
diff --git a/src/metaflac/operations.c b/src/metaflac/operations.c
index c8f5b37..e29311b 100644
--- a/src/metaflac/operations.c
+++ b/src/metaflac/operations.c
@@ -213,9 +213,71 @@
 
 FLAC__bool do_major_operation__append(FLAC__Metadata_Chain *chain, const CommandLineOptions *options)
 {
-	(void) chain, (void) options;
-	flac_fprintf(stderr, "ERROR: --append not implemented yet\n");
-	return false;
+	FLAC__byte header[FLAC__STREAM_METADATA_HEADER_LENGTH];
+	FLAC__byte *buffer;
+	FLAC__uint32 buffer_size, num_objects = 0, i, append_after = UINT32_MAX;
+	FLAC__StreamMetadata *object;
+	FLAC__Metadata_Iterator *iterator;
+
+	/* First, find out after which block appending should take place */
+	for(i = 0; i < options->args.num_arguments; i++) {
+		if(options->args.arguments[i].type == ARG__BLOCK_NUMBER) {
+			if(append_after != UINT32_MAX || options->args.arguments[i].value.block_number.num_entries > 1)	{
+				flac_fprintf(stderr, "ERROR: more than one block number specified with --append\n");
+				return false;
+			}
+			append_after = options->args.arguments[i].value.block_number.entries[0];
+		}
+	}
+
+	iterator = FLAC__metadata_iterator_new();
+
+	if(0 == iterator)
+		die("out of memory allocating iterator");
+
+	FLAC__metadata_iterator_init(iterator, chain);
+
+	/* Go to requested block */
+	for(i = 0; i < append_after; i++) {
+		if(!FLAC__metadata_iterator_next(iterator))
+			break;
+	}
+
+	/* Read header from stdin */
+	while(fread(header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, stdin) == FLAC__STREAM_METADATA_HEADER_LENGTH) {
+
+		buffer_size = ((FLAC__uint32)(header[1]) << 16) + ((FLAC__uint32)(header[2]) << 8) + header[3];
+		buffer = safe_malloc_(buffer_size + FLAC__STREAM_METADATA_HEADER_LENGTH);
+		memcpy(buffer, header, FLAC__STREAM_METADATA_HEADER_LENGTH);
+
+		if(fread(buffer+FLAC__STREAM_METADATA_HEADER_LENGTH, 1, buffer_size, stdin) < buffer_size) {
+			flac_fprintf(stderr, "ERROR: couldn't read metadata block #%u from stdin\n",(num_objects+1));
+			free(buffer);
+			break;
+		}
+
+		if((object = FLAC__metadata_object_set_raw(buffer, buffer_size + FLAC__STREAM_METADATA_HEADER_LENGTH)) == NULL) {
+			flac_fprintf(stderr, "ERROR: couldn't parse supplied metadata block #%u\n",(num_objects+1));
+			free(buffer);
+			break;
+		}
+		free(buffer);
+
+		if(!FLAC__metadata_iterator_insert_block_after(iterator, object)) {
+			flac_fprintf(stderr, "ERROR: couldn't add supplied metadata block #%u to file\n",(num_objects+1));
+			FLAC__metadata_object_delete(object);
+			FLAC__metadata_iterator_delete(iterator);
+			break;
+		}
+		num_objects++;
+	}
+
+	if(num_objects == 0)
+		flac_fprintf(stderr, "ERROR: unable to find a metadata block in the supplied input\n");
+
+	FLAC__metadata_iterator_delete(iterator);
+
+	return true;
 }
 
 FLAC__bool do_major_operation__remove(FLAC__Metadata_Chain *chain, const CommandLineOptions *options)
diff --git a/src/metaflac/usage.c b/src/metaflac/usage.c
index f9fcf0a..603e328 100644
--- a/src/metaflac/usage.c
+++ b/src/metaflac/usage.c
@@ -280,18 +280,14 @@
 	fprintf(out, "    You may specify --data-format=binary to dump the raw binary form of each\n");
 	fprintf(out, "    metadata block. Specify --data-format=binary-headerless to omit output of\n");
 	fprintf(out, "    metadata block headers, including the id of APPLICATION metadata blocks.\n");
-#if 0
-	fprintf(out, "    The output can be read in using a subsequent call\n");
-	fprintf(out, "    to \"metaflac --append --from-file=...\"\n");
-#endif
+	fprintf(out, "    The output can be read in using a subsequent call to\n");
+	fprintf(out, "    \"metaflac --append\"\n");
 	fprintf(out, "\n");
 	fprintf(out, "    --application-data-format=hexdump|text\n");
 	fprintf(out, "    If the application block you are displaying contains binary data but your\n");
 	fprintf(out, "    --data-format=text, you can display a hex dump of the application data\n");
 	fprintf(out, "    contents instead using --application-data-format=hexdump\n");
 	fprintf(out, "\n");
-#if 0
-	/*@@@ not implemented yet */
 	fprintf(out, "--append\n");
 	fprintf(out, "    Insert a metadata block from a file.  The input file must be in the same\n");
 	fprintf(out, "    format as generated with --list.\n");
@@ -302,6 +298,8 @@
 	fprintf(out, "    of a block before the first STREAMINFO block.  You may not --append another\n");
 	fprintf(out, "    STREAMINFO block.\n");
 	fprintf(out, "\n");
+#if 0
+	/*@@@ not implemented yet */
 	fprintf(out, "    --from-file=filename\n");
 	fprintf(out, "    Mandatory 'option' to specify the input file containing the block contents.\n");
 	fprintf(out, "\n");