First experiments of osirrox ISO-to-disk copying

This commit is contained in:
2008-05-22 19:25:59 +00:00
parent 85b1e5e473
commit a2e0d1aad6
6 changed files with 935 additions and 105 deletions

View File

@ -19,6 +19,7 @@
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>
#include <utime.h>
@ -1330,6 +1331,9 @@ int Xorriso_node_from_path(struct XorrisO *xorriso, IsoImage *volume,
bit1= work purely literally, do not use libisofs
bit2= (with bit1) this is an address in the disk world
bit3= return root directory as "/" and not as ""
bit4= (with bit2) determine type of disk file eff_path
and return 0 if not existing
bit5= (with bit3) this is not a parameter
@return -1 = faulty path format, 0 = not found ,
1 = found simple node , 2 = found directory
*/
@ -1434,6 +1438,15 @@ much_too_long:;
is_dir= LIBISO_ISDIR(node);
}
}
if(flag&16) {
ret= Sfile_type(eff_path,
1|(4*(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&32)))
));
if(ret<0)
return(0);
if(ret==2)
is_dir= 1;
}
return(1+!!is_dir);
}
@ -1461,6 +1474,99 @@ int Xorriso_get_node_by_path(struct XorrisO *xorriso,
}
/* @param flag bit0= *node is already valid
bit1= add extra block for size estimation
*/
int Xorriso_fake_stbuf(struct XorrisO *xorriso, char *path, struct stat *stbuf,
IsoNode **node, int flag)
{
int ret;
IsoImage *volume;
memset((char *) stbuf, 0, sizeof(struct stat));
if(!(flag&1)) {
ret= Xorriso_get_volume(xorriso, &volume, 0);
if(ret<=0)
return(-1);
ret= Xorriso_node_from_path(xorriso, volume, path, node, 1);
if(ret<=0)
*node= NULL;
}
if(*node==NULL)
return(0);
/* >>> stbuf->st_dev */
/* >>> stbuf->st_ino */
stbuf->st_mode= iso_node_get_permissions(*node) & 07777;
if(LIBISO_ISDIR(*node))
stbuf->st_mode|= S_IFDIR;
else if(LIBISO_ISREG(*node))
stbuf->st_mode|= S_IFREG;
else if(LIBISO_ISLNK(*node))
stbuf->st_mode|= S_IFLNK;
else if(LIBISO_ISCHR(*node))
stbuf->st_mode|= S_IFCHR;
else if(LIBISO_ISBLK(*node))
stbuf->st_mode|= S_IFBLK;
else if(LIBISO_ISFIFO(*node))
stbuf->st_mode|= S_IFIFO;
else if(LIBISO_ISSOCK(*node))
stbuf->st_mode|= S_IFSOCK;
/* >>> NG How to represent LIBISO_BOOT ? */
/* >>> With directories this should be : number of subdirs + 2 */
/* >>> ??? How to obtain RR hardlink number for other types ? */
stbuf->st_nlink= 1;
stbuf->st_uid= iso_node_get_uid(*node);
stbuf->st_gid= iso_node_get_gid(*node);
/* >>> stbuf->st_rdev */
if(LIBISO_ISREG(*node))
stbuf->st_size= iso_file_get_size((IsoFile *) *node)+ (2048 * !!(flag&2));
else
stbuf->st_size= 0;
stbuf->st_blksize= 2048;
stbuf->st_blocks= stbuf->st_size / (off_t) 2048;
if(stbuf->st_blocks * (off_t) 2048 != stbuf->st_size)
stbuf->st_blocks++;
stbuf->st_atime= iso_node_get_atime(*node);
stbuf->st_mtime= iso_node_get_mtime(*node);
stbuf->st_ctime= iso_node_get_ctime(*node);
return(1);
}
/* @param flag >>> bit0= follow links (i.e. stat() rather than lstat()
bit1= do not return -2 on sever errors
*/
int Xorriso_iso_lstat(struct XorrisO *xorriso, char *path, struct stat *stbuf,
int flag)
{
int ret;
IsoNode *node;
if(flag&1) {
/* >>> follow link in ISO image */;
}
ret= Xorriso_fake_stbuf(xorriso, path, stbuf, &node, 0);
if(ret>0)
return(0);
if(ret<0)
return(-2);
return(-1);
}
/* @param flag bit0= give directory x-permission where is r-permission
*/
int Xorriso_transfer_properties(struct XorrisO *xorriso, struct stat *stbuf,
@ -1807,7 +1913,7 @@ cannot_lstat:;
sprintf(xorriso->info_text, "Grafting failed: %s = %s",
Text_shellsafe(img_path,sfe,0), Text_shellsafe(stbuf_src,sfe2,0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
ret=0; goto was_problem;
ret= 0; goto was_problem;
}
xorriso->pacifier_count++;
@ -2143,7 +2249,7 @@ attach_source:;
ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt,
disk_path, img_path,
offset, cut_size, &node, flag&8);
if(ret<0) {
if(ret<=0) {
sprintf(xorriso->info_text, "Grafting failed: %s = %s",
Text_shellsafe(img_path,sfe,0), Text_shellsafe(disk_path,sfe2,0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
@ -2232,6 +2338,408 @@ unsupported_type:;
}
/* @param flag bit0= minimal transfer: access permissions only
*/
int Xorriso_restore_properties(struct XorrisO *xorriso, char *disk_path,
IsoNode *node, int flag)
{
int ret;
mode_t mode;
uid_t uid;
gid_t gid;
struct utimbuf utime_buffer;
char sfe[5*SfileadrL];
mode= iso_node_get_permissions(node);
ret= chmod(disk_path, mode);
if(ret==-1) {
sprintf(xorriso->info_text,
"Cannot change access permissions of disk file %s",
Text_shellsafe(disk_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
return(0);
}
if(flag&1)
return(1);
uid= iso_node_get_uid(node);
gid= iso_node_get_gid(node);
chown(disk_path, uid, gid); /* don't complain if it fails */
utime_buffer.actime= iso_node_get_atime(node);
utime_buffer.modtime= iso_node_get_mtime(node);
ret= utime(disk_path,&utime_buffer);
if(ret==-1) {
sprintf(xorriso->info_text,
"Cannot change atime, mtime of disk file %s",
Text_shellsafe(disk_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
return(0);
}
return(1);
}
#ifdef Osirrox_not_yeT
/* @param flag bit0= cut_out mode : base on leaf parent directory
*/
int Xorriso_restore_implict_properties(struct XorrisO *xorriso, IsoDir *dir,
char *full_disk_path, char *disk_path, char *full_img_path, int flag)
{
int ret, nfic, ndc, nfdc, d, i;
char nfi[SfileadrL], nd[SfileadrL], nfd[SfileadrL], *cpt;
char sfe[5*SfileadrL];
struct stat stbuf;
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, full_disk_path, nfd,
1|2|4);
if(ret<=0)
return(ret);
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, nd, 1|2);
if(ret<=0)
return(ret);
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, full_img_path, nfi,
1|2);
if(ret<=0)
return(ret);
nfdc= Sfile_count_components(nfd, 0);
ndc= Sfile_count_components(nd, 0);
nfic= Sfile_count_components(nfi, 0);
d= nfdc-(flag&1)-ndc;
if(d<0)
return(-1);
if(d>nfic)
return(0);
for(i= 0; i<d; i++) {
cpt= strrchr(nfi, '/');
if(cpt==NULL)
return(-1); /* should not happen */
*cpt= 0;
}
if(nfi[0]==0)
strcpy(nfi, "/");
/* >>> CONSTRUCTION SITE */
if(stat(nfi, &stbuf)==-1)
return(0);
Xorriso_transfer_properties(xorriso, &stbuf, (IsoNode *) dir,
((flag&1) && d==0));
sprintf(xorriso->info_text,
"Copied properties for %s", Text_shellsafe(ni, sfe, 0));
sprintf(xorriso->info_text+strlen(xorriso->info_text),
" from %s", Text_shellsafe(nfd, sfe, 0));
if(!((flag&1) && d==0))
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
return(1);
}
#endif /* Osirrox_not_yeT */
/* @param flag bit0= minimal transfer: access permissions only
@return <0 severe error , 0 failure , 1 success
*/
int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node,
char *img_path, char *disk_path, int flag)
{
int ret, write_fd= -1, wanted, wret;
char *what= "[unknown filetype]", sfe[5*SfileadrL], buf[32*1024];
off_t todo, size;
void *stream2= NULL;
if(LIBISO_ISDIR(node)) {
what= "directory";
ret= mkdir(disk_path, 0777);
} else if(LIBISO_ISREG(node)) {
what= "regular file";
/* >>> need to exploit node rather than img_path */
ret= Xorriso_iso_file_open(xorriso, img_path, &stream2, 0);
if(ret<=0)
goto ex;
write_fd= open(disk_path,O_WRONLY|O_EXCL|O_CREAT);
if(write_fd==-1)
goto cannot_restore;
todo= size= iso_file_get_size((IsoFile *) node);
while(todo>0) {
wanted= sizeof(buf);
if(wanted>todo)
wanted= todo;
ret= Xorriso_iso_file_read(xorriso, stream2, buf, wanted, 0);
if(ret<=0)
break;
wret= write(write_fd, buf, ret);
if(wret>=0)
todo-= wret;
if(wret != ret) {
sprintf(xorriso->info_text,
"Cannot write all bytes to disk filesystem path %s",
Text_shellsafe(disk_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
break;
}
}
close(write_fd);
write_fd= -1;
Xorriso_iso_file_close(xorriso, &stream2, 0);
stream2= NULL;
ret= (todo==0);
} else if(LIBISO_ISLNK(node)) {
what= "symbolic link";
goto not_this_type;
/* >>> restore symbolic link */;
} else if(LIBISO_ISCHR(node)) {
what= "character device";
goto not_this_type;
/* >>> restore character device */;
} else if(LIBISO_ISBLK(node)) {
what= "block device";
goto not_this_type;
/* >>> restore block device */;
} else if(LIBISO_ISFIFO(node)) {
what= "named pipe";
goto not_this_type;
/* >>> restore fifo */;
} else if(LIBISO_ISSOCK(node)) {
what= "";
/* restoring a socket file makes no sense */;
} else {
not_this_type:;
sprintf(xorriso->info_text, "Cannot restore file type '%s'", what);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
ret= 0; goto ex;
}
if(ret==-1) {
cannot_restore:;
sprintf(xorriso->info_text,
"Cannot restore %s to disk filesystem: %s",
what, Text_shellsafe(img_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
ret= 0; goto ex;
}
ret= Xorriso_restore_properties(xorriso, disk_path, node, flag&1);
ex:;
if(write_fd>0)
close(write_fd);
Xorriso_iso_file_close(xorriso, &stream2, 0);
return(ret);
}
/*
@param flag
>>> bit0= mkdir: graft in as empty directory, not as copy from iso
bit1= do not report copied files
bit2= -follow, -not_*: this is not a command parameter
??? <<< bit3= use offset and cut_size for cut_out_node
bit4= return 3 on rejection by exclusion or user
bit5= if directory then do not add sub tree
bit6= this is a copy action: do not fake times and ownership
@return <=0 = error , 1 = added leaf file object , 2 = added directory ,
3 = rejected
*/
int Xorriso_restore(struct XorrisO *xorriso,
char *img_path, char *disk_path, int flag)
{
IsoImage *volume;
char path[SfileadrL], *apt, *npt, sfe[5*SfileadrL], sfe2[5*SfileadrL];
char *img_path_pt;
IsoNode *node= NULL;
int done= 0, is_dir= 0, ret, target_is_dir, source_is_dir, stbuf_ret;
int target_is_split;
struct stat stbuf, target_stbuf;
ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&4));
if(ret<0)
return(ret);
if(ret>0)
return(3*!!(flag&16));
ret= Xorriso_get_volume(xorriso, &volume, 0);
if(ret<=0)
return(ret);
strncpy(path, disk_path, sizeof(path)-1);
path[sizeof(path)-1]= 0;
apt= npt= path;
if(!(flag&1)) {
ret= Xorriso_fake_stbuf(xorriso, img_path, &stbuf, &node, 0);
if(ret>0) {
if(S_ISDIR(stbuf.st_mode))
is_dir= 1;
#ifdef Osirrox_not_yeT
else if((stbuf.st_mode&S_IFMT)==S_IFLNK &&
(xorriso->do_follow_links ||
(xorriso->do_follow_param && !(flag&4)))) {
resolve_link= 1;
ret= Xorriso_iso_lstat(xorriso, img_path, &stbuf, 1|2);
if(ret!=-1) {
if(S_ISDIR(stbuf.st_mode))
is_dir= 1;
}
}
#endif /* Osirrox_not_yeT */
} else {
Xorriso_process_msg_queues(xorriso,0);
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
sprintf(xorriso->info_text,
"Cannot determine attributes of (ISO) source file %s",
Text_shellsafe(img_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
return(0);
}
}
for(npt= apt; !done; apt= npt+1) {
npt= strchr(apt, '/');
if(npt==NULL) {
npt= apt+strlen(apt);
done= 1;
} else
*npt= 0;
if(*apt==0) {
*apt= '/';
apt++;
if(done)
goto attach_source;
continue;
}
source_is_dir= (is_dir || (flag&1) || !done);
stbuf_ret= stat(path, &target_stbuf);
if(stbuf_ret!=-1) {
target_is_dir= S_ISDIR(target_stbuf.st_mode);
target_is_split= 0;
#ifdef Osirrox_not_yeT
/* >>> */
if(target_is_dir)
target_is_split= Xorriso_is_split(xorriso, node, 0);
#endif
if(!((target_is_dir && !target_is_split) && source_is_dir)) {
Xorriso_process_msg_queues(xorriso,0);
/* handle overwrite situation */;
if(xorriso->do_overwrite==1 ||
(xorriso->do_overwrite==2 && !(target_is_dir && !target_is_split))) {
ret= Xorriso_rmx(xorriso, (off_t) 0, path, 1|8);
if(ret<=0)
return(ret);
if(ret==3) {
sprintf(xorriso->info_text, "User revoked restoring of: %s",
Text_shellsafe(disk_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
return(3*!!(flag&16));
}
stbuf_ret= -1;
goto handle_path_node;
}
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
sprintf(xorriso->info_text,
"While restoring '%s' : '%s' exists and may not be overwritten",
disk_path, path);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
}
handle_path_node:;
if(stbuf_ret==-1 && source_is_dir) { /* make a directory */
ret= mkdir(path, 0777);
if(ret==-1) {
Xorriso_process_msg_queues(xorriso,0);
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
Xorriso_report_iso_error(xorriso, disk_path, ret,
"Cannot create disk directory", 0, "FAILURE", 1);
sprintf(xorriso->info_text,
"While restoring '%s' : could not insert '%s'", disk_path, path);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
#ifdef Osirrox_not_yeT
if(disk_path!=NULL && !done)
Xorriso_restore_implict_properties(xorriso, dir, disk__path, path,
image_path, !!(flag&8));
#endif /* Osirrox_not_yeT */
}
if(done) {
attach_source:;
if(flag&1) {
/* directory was created above */;
} else if(is_dir) {
Xorriso_restore_properties(xorriso, disk_path, node, !!(flag&64));
#ifdef Osirrox_not_yeT
if(!(flag&32)) {
ret= Xorriso_add_tree(xorriso, dir, img_path, disk_path, NULL,
flag&2);
if(ret<=0)
return(ret);
}
#endif
} else {
#ifdef Osirrox_not_yeT
if(resolve_link) {
ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0);
if(ret<=0)
return(ret);
disk_path_pt= resolved_disk_path;
} else
#endif /* Osirrox_not_yeT */
img_path_pt= img_path;
ret= Xorriso_tree_restore_node(xorriso, node, img_path_pt, path,
!!(flag&64));
if(ret<=0) {
sprintf(xorriso->info_text, "Restoring failed: %s = %s",
Text_shellsafe(img_path,sfe,0), Text_shellsafe(disk_path,sfe2,0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
xorriso->pacifier_count++;
if(xorriso->pacifier_count%100 && !(flag&2))
Xorriso_pacifier_callback(xorriso, "files restored",
xorriso->pacifier_count,
xorriso->pacifier_total, "", 0);
}
} else
*npt= '/';
}
Xorriso_process_msg_queues(xorriso,0);
return(1+!!is_dir);
}
int Xorriso_process_msg_queues(struct XorrisO *xorriso, int flag)
{
int ret, error_code= 0, os_errno= 0, count= 0, pass, imgid, tunneled;
@ -3635,90 +4143,6 @@ ex:;
}
/* @param flag bit0= *node is already valid
bit1= add extra block for size estimation
*/
int Xorriso_fake_stbuf(struct XorrisO *xorriso, char *path, struct stat *stbuf,
IsoNode **node, int flag)
{
int ret;
IsoImage *volume;
memset((char *) stbuf, 0, sizeof(struct stat));
if(!(flag&1)) {
ret= Xorriso_get_volume(xorriso, &volume, 0);
if(ret<=0)
return(-1);
ret= Xorriso_node_from_path(xorriso, volume, path, node, 1);
if(ret<=0)
*node= NULL;
}
if(*node==NULL)
return(0);
/* >>> stbuf->st_dev */
/* >>> stbuf->st_ino */
stbuf->st_mode= iso_node_get_permissions(*node) & 07777;
if(LIBISO_ISDIR(*node))
stbuf->st_mode|= S_IFDIR;
else if(LIBISO_ISREG(*node))
stbuf->st_mode|= S_IFREG;
else if(LIBISO_ISLNK(*node))
stbuf->st_mode|= S_IFLNK;
else if(LIBISO_ISLNK(*node))
stbuf->st_mode|= S_IFCHR;
else if(LIBISO_ISBLK(*node))
stbuf->st_mode|= S_IFBLK;
else if(LIBISO_ISFIFO(*node))
stbuf->st_mode|= S_IFIFO;
else if(LIBISO_ISSOCK(*node))
stbuf->st_mode|= S_IFSOCK;
/* >>> NG How to represent LIBISO_BOOT ? */
/* >>> With directories this should be : number of subdirs + 2 */
/* >>> ??? How to obtain RR hardlink number for other types ? */
stbuf->st_nlink= 1;
stbuf->st_uid= iso_node_get_uid(*node);
stbuf->st_gid= iso_node_get_gid(*node);
/* >>> stbuf->st_rdev */
if(LIBISO_ISREG(*node))
stbuf->st_size= iso_file_get_size((IsoFile *) *node)+ (2048 * !!(flag&2));
else
stbuf->st_size= 0;
stbuf->st_blksize= 2048;
stbuf->st_blocks= stbuf->st_size / (off_t) 2048;
if(stbuf->st_blocks * (off_t) 2048 != stbuf->st_size)
stbuf->st_blocks++;
stbuf->st_atime= iso_node_get_atime(*node);
stbuf->st_mtime= iso_node_get_mtime(*node);
stbuf->st_ctime= iso_node_get_ctime(*node);
return(1);
}
int Xorriso_iso_lstat(struct XorrisO *xorriso, char *path, struct stat *stbuf,
int flag)
{
int ret;
IsoNode *node;
ret= Xorriso_fake_stbuf(xorriso, path, stbuf, &node, 0);
if(ret>0)
return(0);
if(ret<0)
return(-2);
return(-1);
}
int Xorriso_sorted_dir_i(struct XorrisO *xorriso, IsoDir *dir_node,
int *filec, char ***filev, off_t boss_mem, int flag)
{