New command -concat

This commit is contained in:
2014-04-21 13:18:38 +00:00
parent 8d4867c9a4
commit 642ec7ca89
17 changed files with 712 additions and 129 deletions

View File

@ -1506,19 +1506,30 @@ ex:;
/* @param flag bit0= path is a directory
bit2= recursion: do not reassure in mode 2 "tree"
bit3= this is for overwriting and not for plain removal
bit3-7= question text mode
0= plain removal
1= replacing file object
2= overwriting of content, keeping file object
3= appending of content, keeping file object
*/
int Xorriso_reassure_restore(struct XorrisO *xorriso, char *path, int flag)
{
int ret;
int ret, mode;
mode= (flag >> 3) & 31;
while((xorriso->do_reassure==1 || (xorriso->do_reassure==2 && !(flag&4)))
&& !xorriso->request_not_to_ask) {
/* ls -ld */
Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 1|2|8);
if(flag&1) /* du -s */
Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 2|4);
if(flag&8)
if(mode == 3)
sprintf(xorriso->info_text,
"File exists. Append content ? n= no, y= yes, x= abort, @= stop asking\n");
else if(mode == 2)
sprintf(xorriso->info_text,
"File exists. Overwrite content ? n= no, y= yes, x= abort, @= stop asking\n");
else if(mode == 1)
sprintf(xorriso->info_text,
"File exists. Remove ? n= keep old, y= remove, x= abort, @= stop asking\n");
else
@ -1530,7 +1541,7 @@ int Xorriso_reassure_restore(struct XorrisO *xorriso, char *path, int flag)
goto ex;
if(xorriso->request_to_abort) {
sprintf(xorriso->info_text,
"Removal operation aborted by user before file: ");
"File alteration operation aborted by user before file: ");
Text_shellsafe(path, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
ret= 3; goto ex;
@ -1960,3 +1971,187 @@ int Xorriso_append_scdbackup_record(struct XorrisO *xorriso, int flag)
return(1);
}
/* @param flag bit0= for append rather than overwrite
*/
int Xorriso_is_concat_target(struct XorrisO *xorriso, char *target,
int *ftype, int *fd, int flag)
{
int ret;
char *why= "";
*ftype= 0;
*fd = -1;
if(strcmp(target, "-") == 0) {
*fd= 1;
*ftype= 8; /* character device */
return(1);
}
*ftype= Sfile_type(target, 1 | 8 | 16);
if(*ftype == -1)
return(2); /* not yet existing regular */
if(*ftype & 1024) {
*fd= Sfile_get_dev_fd_no(target, 0);
*ftype &= ~1024;
}
if(*ftype & 2048) {
why= "fstat(2) returned -1 on file descriptor number.";
goto not_usable;
}
if(*ftype == 3) {
/* >>>
if follow_links is enabled : obtain target type
*ftype= Sfile_type(target, 1 | 4 | 8);
else
*/
why= "May not follow symbolic link.";
goto not_usable;
}
if(*ftype == 2) {
why= "May not write data into a directory.";
goto not_usable;
}
if(*ftype == 0) {
why= "Cannot determine file type.";
goto not_usable;
}
if(*ftype == 7) {
/* >>> what to do with UNIX socket ? */;
why= "Cannot yet handle socket file as target.";
goto not_usable;
}
if(xorriso->do_overwrite != 1 && xorriso->do_overwrite != 2) {
why= "May not alter existing file.";
goto not_usable;
}
ret= Xorriso_reassure_restore(xorriso, target, (2 + (flag & 1)) << 3);
if(ret <= 0 || ret == 0) {
why= "User revoked alteration of existing file.";
goto not_usable;
}
if(*ftype == 1)
return(2); /* existing regular */
if(*ftype == 4 || *ftype == 6 || *ftype == 8)
return(1); /* named pipe, block device, character device */
not_usable:;
sprintf(xorriso->info_text,
"Unsuitable -concat target: ");
Text_shellsafe(target, xorriso->info_text, 1);
sprintf(xorriso->info_text + strlen(xorriso->info_text), ". %s", why);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
int Xorriso_concat(struct XorrisO *xorriso, char *mode, char *target,
int progc, char **progv,
int filec, char **filev, int flag)
{
int ret, i, fd= -1, target_is_regular= 0, fd_opened= 0, ftype, prog_forked= 0;
int status;
int open_mode= O_WRONLY | O_CREAT;
struct stat stbuf;
pid_t forked_pid;
for(i= 0; i < filec; i++) {
ret= Xorriso_iso_lstat(xorriso, filev[i], &stbuf, 4);
if(ret == -1)
goto ex;
if(!S_ISREG(stbuf.st_mode)) {
sprintf(xorriso->info_text,
"-concat: iso_rr_path is not a regular data file: ");
Text_shellsafe(filev[i], xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
ret= 0; goto ex;
}
}
if(strcmp(mode, "overwrite") == 0) {
ret= Xorriso_is_concat_target(xorriso, target, &ftype, &fd, 0);
if(ret <= 0)
goto ex;
if(ret == 2) {
target_is_regular= 1;
open_mode |= O_TRUNC;
}
if(fd == -1) {
fd= open(target, O_WRONLY | O_TRUNC | O_CREAT, 0666);
fd_opened= 1;
}
} else if(strcmp(mode, "append") == 0) {
ret= Xorriso_is_concat_target(xorriso, target, &ftype, &fd, 1);
if(ret <= 0)
goto ex;
target_is_regular= (ret == 2);
if(fd == -1) {
fd= open(target, O_WRONLY | O_CREAT, 0666);
fd_opened= 1;
if(fd != -1 && target_is_regular) {
ret= lseek(fd, (off_t) 0, SEEK_END);
if(ret == -1) {
sprintf(xorriso->info_text,
"-concat append: Cannot lseek(2) to file end of ");
Text_shellsafe(target, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
ret= 0; goto ex;
}
}
}
} else if(strcmp(mode, "pipe") == 0) {
ret= Xorriso_pipe_open(xorriso, "-concat pipe", progv[0], progc, progv,
"", &fd, &forked_pid, 2 | 8);
if(ret <= 0)
goto ex;
fd_opened= 1;
prog_forked= 1;
} else {
sprintf(xorriso->info_text, "-concat: Unknown mode ");
Text_shellsafe(mode, xorriso->info_text, 1);
strcat(xorriso->info_text, ". Known modes: overwrite, append, pipe");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
ret= 0; goto ex;
}
if(fd == -1) {
sprintf(xorriso->info_text,
"-concat: Cannot open file handle to ");
Text_shellsafe(target, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
ret= 0; goto ex;
}
for(i= 0; i < filec; i++) {
ret= Xorriso_iso_file_to_fd(xorriso, filev[i], fd, 0);
if(ret <= 0) {
if(i < filec - 1) {
ret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
if(ret < 0) {
sprintf(xorriso->info_text,
"-concat: Aborted although %d files stay unprocessed.",
filec - i + 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
ret= 0; goto ex;
}
}
}
}
ret= 1;
ex:;
if(fd_opened && fd != -1)
close(fd);
if(prog_forked)
Xorriso_wait_child_end(xorriso, forked_pid, &status, 0);
return(ret);
}