⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 file.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
            	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, &regs);
    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 + -