--- file.c 2004-01-23 09:41:32.000000000 +0000 +++ new_file.c 2004-10-30 14:34:24.000000000 +0100 @@ -577,10 +577,14 @@ { assert(!data || length > 0); - if (data && - ((file->ntags == 1 && !(file->flags & ID3_FILE_FLAG_ID3V1)) || - (file->ntags == 2 && (file->flags & ID3_FILE_FLAG_ID3V1))) && - file->tags[0].length == length) { + if (!data + || (!(file->ntags == 1 && !(file->flags & ID3_FILE_FLAG_ID3V1)) && + !(file->ntags == 2 && (file->flags & ID3_FILE_FLAG_ID3V1)))) { + /* no v2 tag. nothing to do */ + goto done; + } + + if (file->tags[0].length == length) { /* easy special case: rewrite existing tag in-place */ if (fseek(file->iofile, file->tags[0].location, SEEK_SET) == -1 || @@ -589,11 +593,46 @@ return -1; goto done; + } else { + /* the new tag has a different size */ + int file_size; + int remainder_size; + char *remainder; + + /* read in the remainder of the file */ + fseek(file->iofile, 0, SEEK_END); + file_size = ftell(file->iofile); + remainder_size = file_size - file->tags[0].location - file->tags[0].length; + remainder = (char*)malloc(remainder_size); + if (fseek(file->iofile, file->tags[0].location + file->tags[0].length, SEEK_SET) == -1 || + fread(remainder, remainder_size, 1, file->iofile) != 1) { + free(remainder); + return -1; + } + + /* write the tag where the old one was */ + if (fseek(file->iofile, file->tags[0].location, SEEK_SET) == -1 || + fwrite(data, length, 1, file->iofile) != 1) { + free(remainder); + return -1; + } + + /* write the reaminder */ + if (fwrite(remainder, remainder_size, 1, file->iofile) != 1) { + free(remainder); + return -1; } - /* hard general case: rewrite entire file */ + free(remainder); - /* ... */ + /* flush the FILE */ + if (fflush(file->iofile) == EOF) + return -1; + + /* truncate if required */ + if (ftell(file->iofile) < file_size) + ftruncate(fileno(file->iofile), ftell(file->iofile)); + } done: return 0;