7 Commits
1.0 ... 1.1

Author SHA1 Message Date
fcd647003b in-place 2013-01-02 10:59:43 +01:00
a8e22fb5db remove broken file on failure 2013-01-02 10:21:33 +01:00
f75e484ebb set-all: do not ignore the last unterminated line 2013-01-02 10:13:41 +01:00
6f6cf8024b readme: requirements 2013-01-02 10:04:25 +01:00
f1828d926f sentinel option 2013-01-01 23:35:11 +01:00
1021b4394d check in before out
so as not to create empty files
2013-01-01 23:31:25 +01:00
1e138ad00d bump version: 1.1 2013-01-01 23:28:09 +01:00
3 changed files with 88 additions and 35 deletions

View File

@ -3,6 +3,12 @@ opustags
View and edit Opus comments.
Requirements
------------
* A POSIX-compliant system,
* libogg.
Installing
----------

View File

@ -1,4 +1,4 @@
.TH opustags 1 "January 1st 2013"
.TH opustags 1 "January 2013"
.SH NAME
opustags \- Opus comment editor
.SH SYNOPSIS
@ -26,6 +26,7 @@ This could be useful to preview some changes before writing them.
As for the edition mode, you need to specify an output file (or \fB-\fP for
\fBstdout\fP). It must be different from the input file.
You may want to use \fB--overwrite\fP if you know what youre doing.
To overwrite the input file, use \fB--in-place\fP.
.PP
Tag edition can be made with the \fB--add\fP, \fB--delete\fP and \fB--set\fP
options. They can be written in any order and dont conflict with each other.
@ -57,6 +58,14 @@ specified output file. If \fIFILE\fP is \fB-\fP then the resulting Opus file
will be written to \fBstdout\fP. As the input file is read incrementally, the
output file cant be the same as the input file.
.TP
.B \-i, \-\-in-place \fR[\fP\fISUFFIX\fP\fR]\fP
Use this when you want to modify the input file in-place. This creates a
temporary file with the specified suffix (.otmp by default). This implies
\fB--overwrite\fP in that if a file with the same temporary name already
exists, it will be overwritten without warning. Of course, this overwrites
the input file too. You cannot use this option when the input file is actually
\fBstdin\fP.
.TP
.B \-y, \-\-overwrite
By default, \fBopustags\fP refuses to overwrite an already existent file. Use
this option to allow that. Note that this doesnt allow in-place edition, the
@ -89,10 +98,9 @@ or \fB--set\fP, which, in that case, are equivalent.
.B \-S, \-\-set-all
Sets the tags from scratch. All the original tags are deleted and new ones are
read from \fBstdin\fP. Each line must specify a \fIFIELD=VALUE\fP pair and be
LF-terminated. If the last line isnt terminated when the end of the stream is
reached, it is ignored. Invalid lines are skipped and cause a warning to be
issued. This could be useful for batch processing tags through an utility like
\fBsed\fP.
LF-terminated (except for the last line). Invalid lines are skipped and cause
a warning to be issued. Blank lines are ignored. This mode could be useful for
batch processing tags through an utility like \fBsed\fP.
.SH SEE ALSO
.BR vorbiscomment (1),
.BR sed (1)

View File

@ -156,7 +156,7 @@ int write_page(ogg_page *og, FILE *stream){
return 0;
}
const char *version = "opustags version 1.0\n";
const char *version = "opustags version 1.1\n";
const char *usage =
"Usage: opustags --help\n"
@ -167,6 +167,7 @@ const char *help =
"Options:\n"
" -h, --help print this help\n"
" -o, --output write the modified tags to a file\n"
" -i, --in-place [SUFFIX] use a temporary file then replace the original file\n"
" -y, --overwrite overwrite the output file if it already exists\n"
" -d, --delete FIELD delete all the fields of a specified type\n"
" -a, --add FIELD=VALUE add a field\n"
@ -177,12 +178,14 @@ const char *help =
struct option options[] = {
{"help", no_argument, 0, 'h'},
{"output", required_argument, 0, 'o'},
{"in-place", optional_argument, 0, 'i'},
{"overwrite", no_argument, 0, 'y'},
{"delete", required_argument, 0, 'd'},
{"add", required_argument, 0, 'a'},
{"set", required_argument, 0, 's'},
{"delete-all", no_argument, 0, 'D'},
{"set-all", no_argument, 0, 'S'}
{"set-all", no_argument, 0, 'S'},
{NULL, 0, 0, 0}
};
int main(int argc, char **argv){
@ -191,7 +194,7 @@ int main(int argc, char **argv){
fputs(usage, stdout);
return EXIT_SUCCESS;
}
const char *path_in, *path_out = NULL;
char *path_in, *path_out = NULL, *inplace = NULL;
const char* to_add[argc];
const char* to_delete[argc];
int count_add = 0, count_delete = 0;
@ -200,7 +203,7 @@ int main(int argc, char **argv){
int overwrite = 0;
int print_help = 0;
int c;
while((c = getopt_long(argc, argv, "ho:yd:a:s:DS", options, NULL)) != -1){
while((c = getopt_long(argc, argv, "ho:i::yd:a:s:DS", options, NULL)) != -1){
switch(c){
case 'h':
print_help = 1;
@ -208,6 +211,9 @@ int main(int argc, char **argv){
case 'o':
path_out = optarg;
break;
case 'i':
inplace = optarg == NULL ? ".otmp" : optarg;
break;
case 'y':
overwrite = 1;
break;
@ -248,6 +254,10 @@ int main(int argc, char **argv){
fputs("invalid arguments\n", stderr);
return EXIT_FAILURE;
}
if(inplace && path_out){
fputs("cannot combine --in-place and --output\n", stderr);
return EXIT_FAILURE;
}
path_in = argv[optind];
if(path_out != NULL && strcmp(path_in, "-") != 0){
char canon_in[PATH_MAX+1], canon_out[PATH_MAX+1];
@ -258,30 +268,14 @@ int main(int argc, char **argv){
}
}
}
FILE *out = NULL;
if(path_out != NULL){
if(strcmp(path_out, "-") == 0)
out = stdout;
else{
if(!overwrite){
if(access(path_out, F_OK) == 0){
fprintf(stderr, "'%s' already exists (use -y to overwrite)\n", path_out);
return EXIT_FAILURE;
}
}
out = fopen(path_out, "w");
if(!out){
perror("fopen");
return EXIT_FAILURE;
}
}
}
FILE *in;
if(strcmp(path_in, "-") == 0){
if(set_all){
fputs("can't open stdin for input when -S is specified\n", stderr);
if(out)
fclose(out);
return EXIT_FAILURE;
}
if(inplace){
fputs("cannot modify stdin 'in-place'\n", stderr);
return EXIT_FAILURE;
}
in = stdin;
@ -290,10 +284,40 @@ int main(int argc, char **argv){
in = fopen(path_in, "r");
if(!in){
perror("fopen");
if(out)
fclose(out);
return EXIT_FAILURE;
}
FILE *out = NULL;
if(inplace != NULL){
path_out = malloc(strlen(path_in) + strlen(inplace) + 1);
if(path_out == NULL){
fputs("failure to allocate memory\n", stderr);
fclose(in);
return EXIT_FAILURE;
}
strcpy(path_out, path_in);
strcat(path_out, inplace);
}
if(path_out != NULL){
if(strcmp(path_out, "-") == 0)
out = stdout;
else{
if(!overwrite && !inplace){
if(access(path_out, F_OK) == 0){
fprintf(stderr, "'%s' already exists (use -y to overwrite)\n", path_out);
fclose(in);
return EXIT_FAILURE;
}
}
out = fopen(path_out, "w");
if(!out){
perror("fopen");
fclose(in);
if(inplace)
free(path_out);
return EXIT_FAILURE;
}
}
}
ogg_sync_state oy;
ogg_stream_state os, enc;
ogg_page og;
@ -380,16 +404,19 @@ int main(int argc, char **argv){
}
else{
char *raw_comment[256];
size_t raw_len = fread(raw_tags, 1, 16384, stdin);
if(raw_len == 16384)
size_t raw_len = fread(raw_tags, 1, 16383, stdin);
if(raw_len == 16383)
fputs("warning: truncating comment to 16 KiB\n", stderr);
raw_tags[raw_len] = '\0';
uint32_t raw_count = 0;
size_t field_len = 0;
int caught_eq = 0;
size_t i = 0;
char *cursor = raw_tags;
for(i=0; i<raw_len && raw_count < 256; i++){
if(raw_tags[i] == '\n'){
for(i=0; i <= raw_len && raw_count < 256; i++){
if(raw_tags[i] == '\n' || raw_tags[i] == '\0'){
if(field_len == 0)
continue;
if(caught_eq)
raw_comment[raw_count++] = cursor;
else
@ -460,7 +487,19 @@ int main(int argc, char **argv){
error = "opustags: invalid file";
if(error){
fprintf(stderr, "%s\n", error);
if(path_out != NULL && out != stdout)
remove(path_out);
if(inplace)
free(path_out);
return EXIT_FAILURE;
}
else if(inplace){
if(rename(path_out, path_in) == -1){
perror("rename");
free(path_out);
return EXIT_FAILURE;
}
free(path_out);
}
return EXIT_SUCCESS;
}