new prototype for copy_file(), improve error reporting

This commit is contained in:
Christophe Grenier 2023-08-25 11:43:50 +02:00
parent a8b22a5eed
commit 979489eff6
8 changed files with 89 additions and 62 deletions

View file

@ -39,8 +39,10 @@ extern "C" {
#define CAPA_LIST_DELETED 1
#define CAPA_LIST_ADS 2
typedef enum { CP_OK=0, CP_STAT_FAILED=-1, CP_OPEN_FAILED=-2, CP_READ_FAILED=-3, CP_CREATE_FAILED=-4, CP_NOSPACE=-5, CP_CLOSE_FAILED=-6, CP_NOMEM=-7} copy_file_t;
typedef enum { DIR_PART_ENOIMP=-3, DIR_PART_ENOSYS=-2, DIR_PART_EIO=-1, DIR_PART_OK=0} dir_partition_t;
typedef struct dir_data dir_data_t;
typedef struct
{
struct td_list_head list;
@ -65,7 +67,7 @@ struct dir_data
unsigned int param;
unsigned int capabilities;
int(*get_dir)(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const unsigned long int first_inode, file_info_t*list);
int (*copy_file)(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
copy_file_t (*copy_file)(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
void (*close)(dir_data_t *dir_data);
char *local_dir;
void *private_dir_data;

View file

@ -49,8 +49,9 @@
#include "askloc.h"
#include "setdate.h"
static int copy_dir(WINDOW *window, disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_info_t *dir, unsigned int *copy_ok, unsigned int *copy_bad);
static int copy_selection(file_info_t*dir_list, WINDOW *window, disk_t *disk, const partition_t *partition, dir_data_t *dir_data, unsigned int *copy_ok, unsigned int *copy_bad);
typedef enum { CD_FINISHED = 0, CD_STOPPED = 1, CD_NOSPACE = 2 } copy_dir_t;
static copy_dir_t copy_dir(WINDOW *window, disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_info_t *dir, unsigned int *copy_ok, unsigned int *copy_bad);
static copy_dir_t copy_selection(file_info_t*dir_list, WINDOW *window, disk_t *disk, const partition_t *partition, dir_data_t *dir_data, unsigned int *copy_ok, unsigned int *copy_bad);
#define INTER_DIR (LINES-25+15)
#define MAX_DIR_NBR 256
@ -79,7 +80,7 @@ static int copy_progress(WINDOW *window, const unsigned int copy_ok, const unsig
return check_enter_key_or_s(window);
}
static void copy_done(WINDOW *window, const unsigned int copy_ok, const unsigned int copy_bad, const unsigned int copy_stopped)
static void copy_done(WINDOW *window, const unsigned int copy_ok, const unsigned int copy_bad, const copy_dir_t copy_stopped)
{
wmove(window,5,0);
wclrtoeol(window);
@ -90,8 +91,10 @@ static void copy_done(WINDOW *window, const unsigned int copy_ok, const unsigned
else
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(2));
}
if(copy_stopped)
if(copy_stopped == CD_STOPPED)
wprintw(window,"Copy stopped! %u ok, %u failed", copy_ok, copy_bad);
else if(copy_stopped == CD_NOSPACE)
wprintw(window,"Copy stopped! %u ok, %u failed - Not enough space", copy_ok, copy_bad);
else
wprintw(window,"Copy done! %u ok, %u failed", copy_ok, copy_bad);
if(has_colors())
@ -434,7 +437,7 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
{
unsigned int copy_bad=0;
unsigned int copy_ok=0;
unsigned int copy_stopped=0;
copy_dir_t copy_stopped=CD_FINISHED;
aff_copy(window);
wmove(window,3,0);
aff_part(window, AFF_PART_ORDER|AFF_PART_STATUS, disk, partition);
@ -450,8 +453,12 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
}
else if(LINUX_S_ISREG(tmp->st_mode)!=0)
{
copy_file_t res;
copy_progress(window, copy_ok, copy_bad);
if(dir_data->copy_file(disk, partition, dir_data, tmp)==0)
res=dir_data->copy_file(disk, partition, dir_data, tmp);
if(res==CP_NOSPACE)
copy_stopped=CD_NOSPACE;
if(res==CP_OK)
copy_ok++;
else
copy_bad++;
@ -487,7 +494,7 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
{
unsigned int copy_bad=0;
unsigned int copy_ok=0;
unsigned int copy_stopped;
copy_dir_t copy_stopped;
aff_copy(window);
wmove(window,3,0);
aff_part(window, AFF_PART_ORDER|AFF_PART_STATUS, disk, partition);
@ -682,7 +689,7 @@ static int can_copy_dir(const file_info_t *current_file, const unsigned long int
return 1;
}
static int copy_dir(WINDOW *window, disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_info_t *dir, unsigned int *copy_ok, unsigned int *copy_bad)
static copy_dir_t copy_dir(WINDOW *window, disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_info_t *dir, unsigned int *copy_ok, unsigned int *copy_bad)
{
static unsigned int dir_nbr=0;
static unsigned long int inode_known[MAX_DIR_NBR];
@ -692,7 +699,7 @@ static int copy_dir(WINDOW *window, disk_t *disk, const partition_t *partition,
struct td_list_head *file_walker = NULL;
TD_INIT_LIST_HEAD(&dir_list.list);
if(dir_data->get_dir==NULL || dir_data->copy_file==NULL)
return 0;
return CD_FINISHED;
inode_known[dir_nbr++]=dir->st_ino;
dir_name=mkdir_local(dir_data->local_dir, dir_data->current_directory);
dir_data->get_dir(disk, partition, dir_data, (const unsigned long int)dir->st_ino, &dir_list);
@ -703,7 +710,7 @@ static int copy_dir(WINDOW *window, disk_t *disk, const partition_t *partition,
dir_data->current_directory[current_directory_namelength]='\0';
if(current_directory_namelength+1+strlen(current_file->name)<sizeof(dir_data->current_directory)-1)
{
int copy_stopped=0;
copy_dir_t copy_stopped=CD_FINISHED;
if(strcmp(dir_data->current_directory,"/"))
strcat(dir_data->current_directory,"/");
strcat(dir_data->current_directory,current_file->name);
@ -716,20 +723,27 @@ static int copy_dir(WINDOW *window, disk_t *disk, const partition_t *partition,
}
else if(LINUX_S_ISREG(current_file->st_mode)!=0)
{
copy_stopped=copy_progress(window, *copy_ok, *copy_bad);
if(dir_data->copy_file(disk, partition, dir_data, current_file)==0)
if(copy_progress(window, *copy_ok, *copy_bad))
copy_stopped=CD_STOPPED;
else
{
const copy_file_t res=dir_data->copy_file(disk, partition, dir_data, current_file);
if(res==CP_NOSPACE)
copy_stopped=CD_NOSPACE;
if(res==CP_OK)
(*copy_ok)++;
else
(*copy_bad)++;
}
if(copy_stopped)
}
if(copy_stopped != CD_FINISHED)
{
dir_data->current_directory[current_directory_namelength]='\0';
delete_list_file(&dir_list);
set_date(dir_name, dir->td_atime, dir->td_mtime);
free(dir_name);
dir_nbr--;
return 1;
return copy_stopped;
}
}
}
@ -738,15 +752,16 @@ static int copy_dir(WINDOW *window, disk_t *disk, const partition_t *partition,
set_date(dir_name, dir->td_atime, dir->td_mtime);
free(dir_name);
dir_nbr--;
return 0;
return CD_FINISHED;
}
static int copy_selection(file_info_t*dir_list, WINDOW *window, disk_t *disk, const partition_t *partition, dir_data_t *dir_data, unsigned int *copy_ok, unsigned int *copy_bad)
static copy_dir_t copy_selection(file_info_t*dir_list, WINDOW *window, disk_t *disk, const partition_t *partition, dir_data_t *dir_data, unsigned int *copy_ok, unsigned int *copy_bad)
{
const unsigned int current_directory_namelength=strlen(dir_data->current_directory);
struct td_list_head *tmpw=NULL;
td_list_for_each(tmpw, &dir_list->list)
{
copy_dir_t copy_stopped=CD_FINISHED;
file_info_t *tmp=td_list_entry(tmpw, file_info_t, list);
if((tmp->status&FILE_STATUS_MARKED)!=0 &&
current_directory_namelength + 1 + strlen(tmp->name) <
@ -759,23 +774,30 @@ static int copy_selection(file_info_t*dir_list, WINDOW *window, disk_t *disk, co
strcat(dir_data->current_directory,tmp->name);
if(LINUX_S_ISDIR(tmp->st_mode)!=0)
{
if(copy_dir(window, disk, partition, dir_data, tmp, copy_ok, copy_bad))
copy_stopped=copy_dir(window, disk, partition, dir_data, tmp, copy_ok, copy_bad);
if(copy_stopped!=CD_FINISHED)
{
dir_data->current_directory[current_directory_namelength]='\0';
return 1;
return copy_stopped;
}
}
else if(LINUX_S_ISREG(tmp->st_mode)!=0)
{
copy_file_t res;
copy_progress(window, *copy_ok, *copy_bad);
if(dir_data->copy_file(disk, partition, dir_data, tmp) == 0)
res=dir_data->copy_file(disk, partition, dir_data, tmp);
if(res==CP_NOSPACE)
copy_stopped=CD_NOSPACE;
if(res == CP_OK)
(*copy_ok)++;
else
(*copy_bad)++;
}
}
dir_data->current_directory[current_directory_namelength]='\0';
if(copy_stopped!=CD_FINISHED)
return copy_stopped;
}
return 0;
return CD_FINISHED;
}
#endif

View file

@ -63,7 +63,7 @@ struct exfat_dir_struct
static int exfat_dir(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const unsigned long int first_cluster, file_info_t *dir_list);
static int exfat_copy(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
static copy_file_t exfat_copy(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
static void dir_partition_exfat_close(dir_data_t *dir_data);
#if 0
@ -426,7 +426,7 @@ static void dir_partition_exfat_close(dir_data_t *dir_data)
free(ls);
}
static int exfat_copy(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file)
static copy_file_t exfat_copy(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file)
{
char *new_file;
FILE *f_out;
@ -446,7 +446,7 @@ static int exfat_copy(disk_t *disk, const partition_t *partition, dir_data_t *di
log_critical("Can't create file %s: \n",new_file);
free(new_file);
free(buffer_file);
return -1;
return CP_CREATE_FAILED;
}
cluster = file->st_ino;
start_exfat1=(uint64_t)le32(exfat_header->fat_blocknr) << exfat_header->blocksize_bits;
@ -473,7 +473,7 @@ static int exfat_copy(disk_t *disk, const partition_t *partition, dir_data_t *di
set_date(new_file, file->td_atime, file->td_mtime);
free(new_file);
free(buffer_file);
return -1;
return CP_NOSPACE;
}
file_size -= toread;
if(file_size>0)
@ -501,5 +501,5 @@ static int exfat_copy(disk_t *disk, const partition_t *partition, dir_data_t *di
set_date(new_file, file->td_atime, file->td_mtime);
free(new_file);
free(buffer_file);
return 0;
return CP_OK;
}

View file

@ -74,7 +74,7 @@ static errcode_t my_read_blk64(io_channel channel, unsigned long long block, int
static errcode_t my_write_blk64(io_channel channel, unsigned long long block, int count, const void *buf);
static void dir_partition_ext2_close(dir_data_t *dir_data);
static int ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
static copy_file_t ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
static struct struct_io_manager my_struct_manager = {
.magic = EXT2_ET_MAGIC_IO_MANAGER,
@ -289,9 +289,9 @@ static void dir_partition_ext2_close(dir_data_t *dir_data)
free(ls);
}
static int ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file)
static copy_file_t ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file)
{
int error=0;
copy_file_t error=CP_OK;
FILE *f_out;
const struct ext2_dir_struct *ls = (const struct ext2_dir_struct *)dir_data->private_dir_data;
char *new_file;
@ -300,7 +300,7 @@ static int ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t
{
log_critical("Can't create file %s: %s\n", new_file, strerror(errno));
free(new_file);
return -4;
return CP_CREATE_FAILED;
}
{
errcode_t retval;
@ -312,7 +312,7 @@ static int ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t
{
free(new_file);
fclose(f_out);
return -1;
return CP_STAT_FAILED;
}
retval = ext2fs_file_open(ls->current_fs, file->st_ino, 0, &e2_file);
@ -320,9 +320,9 @@ static int ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t
log_error("Error while opening ext2 file %s\n", dir_data->current_directory);
free(new_file);
fclose(f_out);
return -2;
return CP_OPEN_FAILED;
}
while (1)
while (error!=CP_NOSPACE)
{
int nbytes;
unsigned int got;
@ -330,7 +330,7 @@ static int ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t
if (retval)
{
log_error("Error while reading ext2 file %s\n", dir_data->current_directory);
error = -3;
error = CP_READ_FAILED;
}
if (got == 0)
break;
@ -338,14 +338,14 @@ static int ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t
if ((unsigned) nbytes != got)
{
log_error("Error while writing file %s\n", new_file);
error = -5;
error = CP_NOSPACE;
}
}
retval = ext2fs_file_close(e2_file);
if (retval)
{
log_error("Error while closing ext2 file\n");
error = -6;
error = CP_CLOSE_FAILED;
}
fclose(f_out);
set_date(new_file, file->td_atime, file->td_mtime);

View file

@ -77,7 +77,7 @@ static int fat1x_rootdir(disk_t *disk_car, const partition_t *partition, const d
@ requires \valid(file);
@ requires \separated(disk_car, partition, dir_data, file);
@*/
static int fat_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
static copy_file_t fat_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
/*@
@ requires \valid(dir_data);
@ -535,7 +535,7 @@ static void dir_partition_fat_close(dir_data_t *dir_data)
@ requires \separated(disk_car, partition, dir_data, file);
@ decreases 0;
@*/
static int fat_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file)
static copy_file_t fat_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file)
{
char *new_file;
FILE *f_out;
@ -555,7 +555,7 @@ static int fat_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *
log_critical("Can't create file %s: \n",new_file);
free(new_file);
free(buffer_file);
return -1;
return CP_CREATE_FAILED;
}
cluster = file->st_ino;
fat_length=le16(fat_header->fat_length)>0?le16(fat_header->fat_length):le32(fat_header->fat32_length);
@ -585,7 +585,7 @@ static int fat_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *
set_date(new_file, file->td_atime, file->td_mtime);
free(new_file);
free(buffer_file);
return -1;
return CP_NOSPACE;
}
file_size -= toread;
if(file_size>0)
@ -613,5 +613,5 @@ static int fat_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *
set_date(new_file, file->td_atime, file->td_mtime);
free(new_file);
free(buffer_file);
return 0;
return CP_OK;
}

View file

@ -152,7 +152,7 @@ static void strip_fn(char *fn)
fn[i]='\0';
}
static int fat_copy_file(disk_t *disk, const partition_t *partition, const unsigned int cluster_size, const uint64_t start_data, const char *recup_dir, const unsigned int dir_num, const unsigned int inode_num, const file_info_t *file)
static copy_file_t fat_copy_file(disk_t *disk, const partition_t *partition, const unsigned int cluster_size, const uint64_t start_data, const char *recup_dir, const unsigned int dir_num, const unsigned int inode_num, const file_info_t *file)
{
char *new_file;
FILE *f_out;
@ -188,7 +188,7 @@ static int fat_copy_file(disk_t *disk, const partition_t *partition, const unsig
log_critical("Can't create file %s: \n",new_file);
free(new_file);
free(buffer_file);
return -1;
return CP_CREATE_FAILED;
}
while(cluster>=2 && cluster<=no_of_cluster+2 && file_size>0)
{
@ -207,7 +207,7 @@ static int fat_copy_file(disk_t *disk, const partition_t *partition, const unsig
set_date(new_file, file->td_atime, file->td_mtime);
free(new_file);
free(buffer_file);
return -1;
return CP_NOSPACE;
}
file_size -= toread;
cluster++;
@ -216,7 +216,7 @@ static int fat_copy_file(disk_t *disk, const partition_t *partition, const unsig
set_date(new_file, file->td_atime, file->td_mtime);
free(new_file);
free(buffer_file);
return 0;
return CP_OK;
}
static pstatus_t fat_unformat_aux(struct ph_param *params, const struct ph_options *options, const uint64_t start_data, alloc_data_t *list_search_space)

View file

@ -113,7 +113,7 @@ static int ntfs_td_list_entry( struct ntfs_dir_struct *ls, const ntfschar *name
const int name_len, const int name_type, const s64 pos,
const MFT_REF mref, const unsigned dt_type);
static int ntfs_dir(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const unsigned long int cluster, file_info_t *dir_list);
static int ntfs_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
static copy_file_t ntfs_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
static void dir_partition_ntfs_close(dir_data_t *dir_data);
/**
@ -337,15 +337,16 @@ static int ntfs_dir(disk_t *disk_car, const partition_t *partition, dir_data_t *
enum { bufsize = 4096 };
static int ntfs_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file)
static copy_file_t ntfs_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file)
{
const unsigned long int first_inode=file->st_ino;
ntfs_inode *inode;
struct ntfs_dir_struct *ls=(struct ntfs_dir_struct*)dir_data->private_dir_data;
copy_file_t res=CP_OK;
inode = ntfs_inode_open (ls->vol, first_inode);
if (!inode) {
log_error("ntfs_copy: ntfs_inode_open failed for %s\n", dir_data->current_directory);
return -1;
return CP_STAT_FAILED;
}
{
char *buffer;
@ -359,7 +360,7 @@ static int ntfs_copy(disk_t *disk_car, const partition_t *partition, dir_data_t
if (!buffer)
{
ntfs_inode_close(inode);
return -2;
return CP_NOMEM;
}
stream_name=strrchr(dir_data->current_directory, ':');
if(stream_name)
@ -384,7 +385,7 @@ static int ntfs_copy(disk_t *disk_car, const partition_t *partition, dir_data_t
log_error("Cannot find attribute type 0x%lx.\n", (long) AT_DATA);
free(buffer);
ntfs_inode_close(inode);
return -3;
return CP_STAT_FAILED;
}
if ((inode->mft_no < 2) && (attr->type == AT_DATA))
block_size = ls->vol->mft_record_size;
@ -413,7 +414,7 @@ static int ntfs_copy(disk_t *disk_car, const partition_t *partition, dir_data_t
ntfs_attr_close(attr);
free(buffer);
ntfs_inode_close(inode);
return -4;
return CP_CREATE_FAILED;
}
offset = 0;
for (;;)
@ -429,6 +430,7 @@ static int ntfs_copy(disk_t *disk_car, const partition_t *partition, dir_data_t
//ntfs_log_info("read %lld bytes\n", bytes_read);
if (bytes_read < 0) {
log_error("ERROR: Couldn't read file");
res=CP_READ_FAILED;
break;
}
if (!bytes_read)
@ -438,6 +440,7 @@ static int ntfs_copy(disk_t *disk_car, const partition_t *partition, dir_data_t
if (written != bytes_read)
{
log_error("ERROR: Couldn't output all data!");
res=CP_NOSPACE;
break;
}
offset += bytes_read;
@ -450,7 +453,7 @@ static int ntfs_copy(disk_t *disk_car, const partition_t *partition, dir_data_t
}
/* Finished with the inode; release it. */
ntfs_inode_close(inode);
return 0;
return res;
}
static void dir_partition_ntfs_close(dir_data_t *dir_data)

View file

@ -471,20 +471,20 @@ static void dir_partition_reiser_close(dir_data_t *dir_data)
free(ls);
}
static int reiser_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file)
static copy_file_t reiser_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file)
{
reiserfs_file_t *in;
FILE *f_out;
char *new_file;
struct rfs_dir_struct *ls=(struct rfs_dir_struct*)dir_data->private_dir_data;
int error=0;
copy_file_t error=CP_OK;
uint64_t file_size;
f_out=fopen_local(&new_file, dir_data->local_dir, dir_data->current_directory);
if(!f_out)
{
log_critical("Can't create file %s: %s\n", new_file, strerror(errno));
free(new_file);
return -4;
return CP_CREATE_FAILED;
}
log_error("Try to open rfs file %s\n", dir_data->current_directory);
log_flush();
@ -494,7 +494,7 @@ static int reiser_copy(disk_t *disk_car, const partition_t *partition, dir_data_
log_error("Error while opening rfs file %s\n", dir_data->current_directory);
free(new_file);
fclose(f_out);
return -1;
return CP_OPEN_FAILED;
}
log_error("open rfs file %s done\n", dir_data->current_directory);
log_flush();
@ -506,12 +506,12 @@ static int reiser_copy(disk_t *disk_car, const partition_t *partition, dir_data_
if (reiserfs_file_read(in, buf, file_size) != file_size)
{
log_error("Error while reading rfs file %s\n", dir_data->current_directory);
error = -3;
error = CP_READ_FAILED;
}
else if (fwrite(buf, file_size, 1, f_out) != 1)
{
log_error("Error while writing file %s\n", new_file);
error = -5;
error = CP_NOSPACE;
}
free(buf);
}
@ -525,12 +525,12 @@ static int reiser_copy(disk_t *disk_car, const partition_t *partition, dir_data_
if (reiserfs_file_read(in, buf, read_size) == 0)
{
log_error("Error while reading rfs file %s\n", dir_data->current_directory);
error = -3;
error = CP_READ_FAILED;
}
else if (fwrite(buf, read_size, 1, f_out) != 1)
{
log_error("Error while writing file %s\n", new_file);
error = -5;
error = CP_NOSPACE;
}
file_size -= read_size;
}