📄 file.c
字号:
s += i + 1;
}
#endif /* WITH_FULL_PATHS */
label_set_text (FileLabel [0], _("Source"));
label_set_text (FileString [0], truncFileString (s));
return check_buttons ();
} else {
label_set_text (FileLabel [0], "");
label_set_text (FileString [0], "");
return check_buttons ();
}
}
static int
show_target (char *s)
{
if (s != NULL){
label_set_text (FileLabel [1], _("Target"));
label_set_text (FileString [1], truncFileString (s));
return check_buttons ();
} else {
label_set_text (FileLabel [1], "");
label_set_text (FileString [1], "");
return check_buttons ();
}
}
static int
show_deleting (char *s)
{
label_set_text (FileLabel [0], _("Deleting"));
label_set_text (FileString [0], truncFileString (s));
return check_buttons ();
}
static int
show_bar (int n, long done, long total)
{
gauge_set_value (ProgressGauge [n], (int) total, (int) done);
gauge_show (ProgressGauge [n], 1);
return check_buttons ();
}
static void
file_eta_show ()
{
int eta_hours, eta_mins, eta_s;
char eta_buffer [30];
if (!showing_eta)
return;
eta_hours = eta_secs / (60 * 60);
eta_mins = (eta_secs - (eta_hours * 60 * 60)) / 60;
eta_s = eta_secs - ((eta_hours * 60 * 60) + eta_mins * 60 );
sprintf (eta_buffer, "ETA %d:%02d.%02d", eta_hours, eta_mins, eta_s);
label_set_text (eta_label, eta_buffer);
}
static void
file_bps_show ()
{
char bps_buffer [30];
if (!showing_bps)
return;
if (bps > 1024){
if (bps > 1024*1024){
sprintf (bps_buffer, "%.2f MBS", bps / (1024*1024.0));
} else
sprintf (bps_buffer, "%.2f KBS", bps / 1024.0);
} else
sprintf (bps_buffer, "%ld BPS", bps);
label_set_text (bps_label, bps_buffer);
}
static int
show_file_progress (long done, long total)
{
if (!verbose)
return check_buttons ();
if (total > 0){
label_set_text (ProgressLabel [0], _("File"));
file_eta_show ();
file_bps_show ();
return show_bar (0, done, total);
} else
return show_no_bar (0);
}
static int
show_count_progress (long done, long total)
{
if (!verbose)
return check_buttons ();
if (total > 0){
label_set_text (ProgressLabel [1], _("Count"));
return show_bar (1, done, total);
} else
return show_no_bar (1);
}
static int
show_bytes_progress (long done, long total)
{
if (!verbose)
return check_buttons ();
if (total > 0){
label_set_text (ProgressLabel [2], _("Bytes"));
return show_bar (2, done, total);
} else
return show_no_bar (2);
}
/* }}} */
/* {{{ Copy routines */
enum CaseConvs { NO_CONV=0, UP_CHAR=1, LOW_CHAR=2, UP_SECT=4, LOW_SECT=8 };
int
convert_case (int c, enum CaseConvs *conversion)
{
if (*conversion & UP_CHAR){
*conversion &= ~UP_CHAR;
return toupper (c);
} else if (*conversion & LOW_CHAR){
*conversion &= ~LOW_CHAR;
return tolower (c);
} else if (*conversion & UP_SECT){
return toupper (c);
} else if (*conversion & LOW_SECT){
return tolower (c);
} else
return c;
}
static int transform_error = 0;
static char *
do_transform_source (char *source)
{
int j, k, l, len;
char *fnsource = x_basename (source);
int next_reg;
enum CaseConvs case_conv = NO_CONV;
static char fntarget [MC_MAXPATHLEN];
len = strlen (fnsource);
j = re_match (&rx, fnsource, len, 0, ®s);
if (j != len) {
transform_error = FILE_SKIP;
return NULL;
}
for (next_reg = 1, j = 0, k = 0; j < strlen (dest_mask); j++) {
switch (dest_mask [j]) {
case '\\':
j++;
if (! isdigit (dest_mask [j])){
/* Backslash followed by non-digit */
switch (dest_mask [j]){
case 'U':
case_conv |= UP_SECT;
case_conv &= ~LOW_SECT;
break;
case 'u':
case_conv |= UP_CHAR;
break;
case 'L':
case_conv |= LOW_SECT;
case_conv &= ~UP_SECT;
break;
case 'l':
case_conv |= LOW_CHAR;
break;
case 'E':
case_conv = NO_CONV;
break;
default:
/* Backslash as quote mark */
fntarget [k++] = convert_case (dest_mask [j], &case_conv);
}
break;
} else {
/* Backslash followed by digit */
next_reg = dest_mask [j] - '0';
/* Fall through */
}
case '*':
if (next_reg < 0 || next_reg >= RE_NREGS
|| regs.start [next_reg] < 0) {
message_1s (1, MSG_ERROR, _(" Invalid target mask "));
transform_error = FILE_ABORT;
return NULL;
}
for (l = regs.start [next_reg]; l < regs.end [next_reg]; l++)
fntarget [k++] = convert_case (fnsource [l], &case_conv);
next_reg ++;
break;
default:
fntarget [k++] = convert_case (dest_mask [j], &case_conv);
break;
}
}
fntarget [k] = 0;
return fntarget;
}
static char *
transform_source (char *source)
{
char *s = strdup (source);
char *q;
/* We remove \n from the filename since regex routines would use \n as an anchor */
/* this is just to be allowed to maniupulate file names with \n on it */
for (q = s; *q; q++){
if (*q == '\n')
*q = ' ';
}
q = do_transform_source (s);
free (s);
return q;
}
void
free_linklist (struct link **linklist)
{
struct link *lp, *lp2;
for (lp = *linklist; lp != NULL; lp = lp2){
lp2 = lp -> next;
free (lp);
}
*linklist = NULL;
}
#ifdef USE_VFS
int
is_in_linklist (struct link *lp, char *path, struct stat *sb)
{
ino_t ino = sb->st_ino;
dev_t dev = sb->st_dev;
vfs *vfs = vfs_type (path);
while (lp) {
if (lp->vfs == vfs && lp->ino == ino && lp->dev == dev )
return 1;
lp = lp->next;
}
return 0;
}
#else
int
is_in_linklist (struct link *lp, char *path, struct stat *sb)
{
ino_t ino = sb->st_ino;
dev_t dev = sb->st_dev;
while (lp) {
if (lp->ino == ino && lp->dev == dev )
return 1;
lp = lp->next;
}
return 0;
}
#endif
/* Returns 0 if the inode wasn't found in the cache and 1 if it was found
and a hardlink was succesfully made */
int
check_hardlinks (char *src_name, char *dst_name, struct stat *pstat)
{
struct link *lp;
vfs *my_vfs = vfs_type (src_name);
ino_t ino = pstat->st_ino;
dev_t dev = pstat->st_dev;
struct stat link_stat;
char *p;
if (vfs_file_is_ftp (src_name))
return 0;
for (lp = linklist; lp != NULL; lp = lp -> next)
if (lp->vfs == my_vfs && lp->ino == ino && lp->dev == dev){
if (!mc_stat (lp->name, &link_stat) && link_stat.st_ino == ino &&
link_stat.st_dev == dev && vfs_type (lp->name) == my_vfs){
p = strchr (lp->name, 0) + 1; /* i.e. where the `name' file
was copied to */
if (vfs_type (dst_name) == vfs_type (p)){
if (!mc_stat (p, &link_stat)){
if (!mc_link (p, dst_name))
return 1;
}
}
}
/* FIXME: Announce we couldn't make the hardlink */
return 0;
}
lp = (struct link *) xmalloc (sizeof (struct link) + strlen (src_name)
+ strlen (dst_name) + 1, "Hardlink cache");
if (lp){
lp->vfs = my_vfs;
lp->ino = ino;
lp->dev = dev;
strcpy (lp->name, src_name);
p = strchr (lp->name, 0) + 1;
strcpy (p, dst_name);
lp->next = linklist;
linklist = lp;
}
return 0;
}
/* Duplicate the contents of the symbolic link src_path in dst_path.
Try to make a stable symlink if the option "stable symlink" was
set in the file mask dialog.
If dst_path is an existing symlink it will be deleted silently
(upper levels take already care of existing files at dst_path).
*/
static int
make_symlink (char *src_path, char *dst_path)
{
char link_target[MC_MAXPATHLEN];
int len;
int return_status;
struct stat sb;
int dst_is_symlink;
if (mc_lstat (dst_path, &sb) == 0 && S_ISLNK (sb.st_mode))
dst_is_symlink = 1;
else
dst_is_symlink = 0;
retry_src_readlink:
len = mc_readlink (src_path, link_target, MC_MAXPATHLEN);
if (len < 0) {
return_status = file_error
(_(" Cannot read source link \"%s\" \n %s "), src_path);
if (return_status == FILE_RETRY)
goto retry_src_readlink;
return return_status;
}
link_target[len] = 0;
if (stable_symlinks && (!vfs_file_is_local (src_path) ||
!vfs_file_is_local (dst_path))) {
message_1s (1, MSG_ERROR, _(" Cannot make stable symlinks across "
"non-local filesystems: \n\n"
" Option Stable Symlinks will be disabled "));
stable_symlinks = 0;
}
if (stable_symlinks && *link_target != PATH_SEP) {
char *p, *q, *r, *s;
p = strdup (src_path);
r = strrchr (p, PATH_SEP);
if (r) {
r[1] = 0;
if (*dst_path == PATH_SEP)
q = strdup (dst_path);
else
q = copy_strings (p, dst_path, 0);
r = strrchr (q, PATH_SEP);
if (r) {
r[1] = 0;
s = copy_strings (p, link_target, NULL);
strcpy (link_target, s);
free (s);
s = diff_two_paths (q, link_target);
if (s) {
strcpy (link_target, s);
free (s);
}
}
free (q);
}
free (p);
}
retry_dst_symlink:
if (mc_symlink (link_target, dst_path) == 0)
/* Success */
return FILE_CONT;
/*
* if dst_exists, it is obvious that this had failed.
* We can delete the old symlink and try again...
*/
if (dst_is_symlink) {
if (!mc_unlink (dst_path))
if (mc_symlink (link_target, dst_path) == 0)
/* Success */
return FILE_CONT;
}
return_status = file_error
(_(" Cannot create target symlink \"%s\" \n %s "), dst_path);
if (return_status == FILE_RETRY)
goto retry_dst_symlink;
return return_status;
}
int
copy_file_file (char *src_path, char *dst_path, int ask_overwrite)
{
#ifndef OS2_NT
uid_t src_uid;
gid_t src_gid;
#endif
char *buf = 0;
int buf_size = 8*1024;
int dest_desc = 0;
int source_desc;
int n_read;
int n_written;
int src_mode; /* The mode of the source file */
struct stat sb, sb2;
struct utimbuf utb;
int dst_exists = 0;
long n_read_total = 0;
long file_size;
int return_status, temp_status;
int do_remote_copy = 0;
int appending = 0;
/* bitmask used to remember which resourses we should release on return
A single goto label is much easier to handle than a bunch of gotos ;-). */
unsigned resources = 0;
return_status = FILE_RETRY;
if (show_source (src_path) == FILE_ABORT
|| show_target (dst_path) == FILE_ABORT)
return FILE_ABORT;
mc_refresh ();
retry_dst_stat:
if (mc_stat (dst_path, &sb2) == 0){
if (S_ISDIR (sb2.st_mode)){
return_status = file_error (_(" Cannot overwrite directory \"%s\" \n %s "),
dst_path);
if (return_status == FILE_RETRY)
goto retry_dst_stat;
return return_status;
}
dst_exists = 1;
}
retry_src_xstat:
if ((*xstat)(src_path, &sb)){
return_status = file_error (_(" Cannot stat source file \"%s\" \n %s "),
src_path);
if (return_status == FILE_RETRY)
goto retry_src_xstat;
return return_status;
}
if (dst_exists){
/* .ado: For OS/2 or NT: no st_ino exists, it is better to just try to
* overwrite the target file
*/
#ifndef OS2_NT
/* Destination already exists */
if (sb.st_dev == sb2.st_dev && sb.st_ino == sb2.st_ino){
message_3s (1, MSG_ERROR, _(" `%s' and `%s' are the same file. "),
src_path, dst_path);
do_refresh ();
return FILE_SKIP;
}
#endif
/* Should we replace destination? */
if (ask_overwrite) {
if (vfs_file_is_ftp (src_path))
do_reget = -1;
else
do_reget = 0;
return_status = query_replace (dst_path, &sb, &sb2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -