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

📄 file.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* {{{ Copyright */

/* File managing.  Important notes on this file:

   About the use of dialogs in this file:
     If you want to add a new dialog box (or call a routine that pops
     up a dialog box), you have to provide a wrapper for background
     operations (ie, background operations have to up-call to the parent
     process).

     For example, instead of using the message() routine, in this
     file, you should use one of the stubs that call message with the
     proper number of arguments (ie, message_1s, message_2s and so on).

     Actually, that is a rule that should be followed by any routines
     that may be called from this module.

*/

/* File managing
   Copyright (C) 1994, 1995, 1996 The Free Software Foundation

   Written by: 1994, 1995       Janne Kukonlehto
               1994, 1995       Fred Leeflang
               1994, 1995, 1996 Miguel de Icaza
               1995, 1996       Jakub Jelinek
	       1997             Norbert Warmuth
	       1998		Pavel Machek

   The copy code was based in GNU's cp, and was written by:
   Torbjorn Granlund, David MacKenzie, and Jim Meyering.

   The move code was based in GNU's mv, and was written by:
   Mike Parker and David MacKenzie.

   Janne Kukonlehto added much error recovery to them for being used
   in an interactive program.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* }}} */

/* {{{ Include files */

#include <config.h>
/* Hack: the vfs code should not rely on this */
#define WITH_FULL_PATHS 1

#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#ifdef OS2_NT
#    include <io.h>
#endif

#include <errno.h>
#include "tty.h"
#include <ctype.h>
#include <malloc.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#endif
#include <sys/stat.h>
#include <sys/param.h>
#include <fcntl.h>
#ifdef SCO_FLAVOR
#	include <sys/timeb.h>	/* alex: for struct timeb, used in time.h */
#endif /* SCO_FLAVOR */
#if defined(_MSC_VER)
#include <sys/time.h___>
#else
#include <time.h>
#endif
#include <utime.h>
#include "mad.h"
#include "regex.h"
#include "util.h"
#include "dialog.h"
#include "global.h"
/* Needed by query_replace */
#include "color.h"
#include "win.h"
#include "dlg.h"
#include "widget.h"
#define WANT_WIDGETS
#include "main.h"		/* WANT_WIDGETS-> we get the the_hint def */
#include "file.h"
#include "layout.h"
#include "widget.h"
#include "wtools.h"
#include "background.h"

/* Needed for current_panel, other_panel and WTree */
#include "dir.h"
#include "panel.h"
#include "tree.h"
#include "key.h"
#include "../vfs/vfs.h"

#include "x.h"

/* }}} */

#if USE_VFS && USE_NETCODE
extern
#else
static
#endif

int do_reget;

/* rcsid [] = "$Id: file.c 15218 2005-05-11 16:50:39Z weiden $" */
int verbose = 1;

/* Recursive operation on subdirectories */
int dive_into_subdirs = 0;

/* When moving directories cross filesystem boundaries delete the successfull
   copied files when all files below the directory and its subdirectories
   were processed.
   If erase_at_end is zero files will be deleted immediately after their
   successful copy (Note: this behaviour is not tested and at the moment
   it can't be changed at runtime) */
int erase_at_end = 1;

/* Preserve the original files' owner, group, permissions, and
   timestamps (owner, group only as root). */
int preserve;

/* The value of the "preserve Attributes" checkbox in the copy file dialog.
   We can't use the value of "preserve" because it can change in order to
   preserve file attributs when moving files across filesystem boundaries
   (we want to keep the value of the checkbox between copy operations). */
int op_preserve = 1;

/* If running as root, preserve the original uid/gid
   (we don't want to try chwon for non root)
   preserve_uidgid = preserve && uid == 0 */
int preserve_uidgid = 0;

/* The bits to preserve in created files' modes on file copy */
int umask_kill = 0777777;

/* If on, it gets a little scrict with dangerous operations */
int know_not_what_am_i_doing = 0;

int stable_symlinks = 0;

/* The next two are not static, since they are used on background.c */
/* Controls appending to files, shared with filequery.c */
int do_append = 0;

/* With ETA on we have extra screen space */
int eta_extra = 0;

/* result from the recursive query */
int recursive_result;

/* The estimated time of arrival in seconds */
double eta_secs;

/* Used to save the hint line */
static int last_hint_line;

/* mapping operations into names */
char *operation_names [] = { "Copy", "Move", "Delete" };

/* This is a hard link cache */
struct link {
    struct link *next;
    vfs *vfs;
    dev_t dev;
    ino_t ino;
    short linkcount;
    umode_t st_mode;
    char name[1];
};

/* the hard link cache */
struct link *linklist = NULL;

/* the files-to-be-erased list */
struct link *erase_list;

/* In copy_dir_dir we use two additional single linked lists: The first -
   variable name `parent_dirs' - holds information about already copied
   directories and is used to detect cyclic symbolic links.
   The second (`dest_dirs' below) holds information about just created
   target directories and is used to detect when an directory is copied
   into itself (we don't want to copy infinitly).
   Both lists don't use the linkcount and name structure members of struct
   link. */
struct link *dest_dirs = 0;

struct re_pattern_buffer rx;
struct re_registers regs;
static char *dest_mask = NULL;

/* To symlinks the difference between `follow Links' checked and not
   checked is the stat call used (mc_stat resp. mc_lstat) */
int (*xstat)(const char *, struct stat *) = mc_lstat;

static int op_follow_links = 0;

/* File operate window sizes */
#define WX 62
#define WY 10
#define BY 10
#define WX_ETA_EXTRA  12

#define FCOPY_GAUGE_X 14
#define FCOPY_LABEL_X 5

/* Used for button result values */
enum {
    REPLACE_YES = B_USER,
    REPLACE_NO,
    REPLACE_APPEND,
    REPLACE_ALWAYS,
    REPLACE_UPDATE,
    REPLACE_NEVER,
    REPLACE_ABORT,
    REPLACE_SIZE,
    REPLACE_REGET
};

enum {
    RECURSIVE_YES,
    RECURSIVE_NO,
    RECURSIVE_ALWAYS,
    RECURSIVE_NEVER,
    RECURSIVE_ABORT
};

/* Pointer to the operate dialog */
static   Dlg_head *op_dlg;
int      showing_eta;
int      showing_bps;
unsigned long bps = 0, bps_time = 0;

static char *op_names [] = { N_(" Copy "), N_(" Move "), N_(" Delete ") };
static int selected_button;
static int last_percentage [3];

/* Replace dialog: color set, descriptor and filename */
static int replace_colors [4];
static Dlg_head *replace_dlg;
static char *replace_filename;
static int replace_result;

static struct stat *s_stat, *d_stat;

static int recursive_erase (char *s);
static int erase_file (char *s);

/* Describe the components in the panel operations window */
static WLabel *FileLabel [2];
static WLabel *FileString [2];
static WLabel *ProgressLabel [3];
static WGauge *ProgressGauge [3];
static WLabel *eta_label;
static WLabel *bps_label;
static WLabel *stalled_label;

/* }}} */

/* {{{ File progress display routines */

#ifndef HAVE_X
static int
check_buttons (void)
{
    int c;
    Gpm_Event event;

    c = get_event (&event, 0, 0);
    if (c == EV_NONE)
      return FILE_CONT;
    dlg_process_event (op_dlg, c, &event);
    switch (op_dlg->ret_value) {
    case FILE_SKIP:
	return FILE_SKIP;
	break;
    case B_CANCEL:
    case FILE_ABORT:
	return FILE_ABORT;
	break;
    default:
	return FILE_CONT;
    }
}
#else

#ifdef HAVE_TK
static int
check_buttons (void)
{
    tk_dispatch_all ();
    if (op_dlg->running)
        return FILE_CONT;
}
#endif /* HAVE_TK */

#ifdef HAVE_XVIEW
static int
check_buttons (void)
{
    xv_dispatch_something ();
    if (op_dlg->running)
        return FILE_CONT;
}
#endif /* HAVE_XVIEW */

#ifdef HAVE_GNOME
#include <gtk/gtk.h>
static int
check_buttons (void)
{
    x_flush_events ();

    if (op_dlg->running)
        return FILE_CONT;

    if (op_dlg->ret_value == B_CANCEL)
	return FILE_ABORT;
    else
	return op_dlg->ret_value;
}
#endif /* HAVE_GNOME */

#endif /* HAVE_X */

static int
op_win_callback (struct Dlg_head *h, int id, int msg)
{
    switch (msg){
#ifndef HAVE_X
    case DLG_DRAW:
	attrset (COLOR_NORMAL);
	dlg_erase (h);
	draw_box (h, 1, 2, h->lines-2, h->cols-4);
	return 1;
#endif
    }
    return 0;
}

void
create_op_win (int op, int with_eta)
{
    int i, x_size;
    int minus = verbose ? 0 : 3;
    int eta_offset = with_eta ? (WX_ETA_EXTRA) / 2 : 0;

#ifdef HAVE_XVIEW
    char *sixty = "                                                                                   ";
    char *fifteen = "               ";
#else
    char *sixty = "";
    char *fifteen = "";
#endif
    replace_result = 0;
    recursive_result = 0;
    showing_eta = with_eta;
    showing_bps = with_eta;
    eta_extra = with_eta ? WX_ETA_EXTRA : 0;
    x_size = (WX + 4) + eta_extra;

    op_dlg = create_dlg (0, 0, WY-minus+4, x_size, dialog_colors,
			 op_win_callback, "", "opwin", DLG_CENTER);

#ifndef HAVE_X
    last_hint_line = the_hint->widget.y;
    if ((op_dlg->y + op_dlg->lines) > last_hint_line)
	the_hint->widget.y = op_dlg->y + op_dlg->lines+1;
#endif

    x_set_dialog_title (op_dlg, "");

    tk_new_frame (op_dlg, "b.");
    add_widgetl (op_dlg, button_new (BY-minus, WX - 19 + eta_offset, FILE_ABORT,
				     NORMAL_BUTTON, _("&Abort"), 0, 0, "abort"),
        XV_WLAY_RIGHTOF);
    add_widgetl (op_dlg, button_new (BY-minus, 14 + eta_offset, FILE_SKIP,
				     NORMAL_BUTTON, _("&Skip"), 0, 0, "skip"),
        XV_WLAY_CENTERROW);

    tk_new_frame (op_dlg, "2.");
    add_widgetl (op_dlg, ProgressGauge [2] = gauge_new (7, FCOPY_GAUGE_X, 0, 100, 0, "g-1"),
        XV_WLAY_RIGHTOF);
    add_widgetl (op_dlg, ProgressLabel [2] = label_new (7, FCOPY_LABEL_X, fifteen, "l-1"),
        XV_WLAY_NEXTROW);
    add_widgetl (op_dlg, bps_label = label_new (7, WX, "", "bps-label"), XV_WLAY_NEXTROW);

        tk_new_frame (op_dlg, "1.");
    add_widgetl (op_dlg, ProgressGauge [1] = gauge_new (8, FCOPY_GAUGE_X, 0, 100, 0, "g-2"),
        XV_WLAY_RIGHTOF);
    add_widgetl (op_dlg, ProgressLabel [1] = label_new (8, FCOPY_LABEL_X, fifteen, "l-2"),
        XV_WLAY_RIGHTOF);
    add_widgetl (op_dlg, stalled_label = label_new (8, WX, "", "stalled"), XV_WLAY_NEXTROW);

    tk_new_frame (op_dlg, "0.");
    add_widgetl (op_dlg, ProgressGauge [0] = gauge_new (6, FCOPY_GAUGE_X, 0, 100, 0, "g-3"),
        XV_WLAY_RIGHTOF);
    add_widgetl (op_dlg, ProgressLabel [0] = label_new (6, FCOPY_LABEL_X, fifteen, "l-3"),
        XV_WLAY_RIGHTOF);
    add_widgetl (op_dlg, eta_label = label_new (6, WX, "", "eta_label"), XV_WLAY_NEXTROW);

    tk_new_frame (op_dlg, "f1.");
    add_widgetl (op_dlg, FileString [1] = label_new (4, FCOPY_GAUGE_X, sixty, "fs-l-1"),
        XV_WLAY_RIGHTOF);
    add_widgetl (op_dlg, FileLabel [1] = label_new (4, FCOPY_LABEL_X, fifteen, "fs-l-2"),
        XV_WLAY_NEXTROW);
    tk_new_frame (op_dlg, "f0.");
    add_widgetl (op_dlg, FileString [0] = label_new (3, FCOPY_GAUGE_X, sixty, "fs-x-1"),
        XV_WLAY_RIGHTOF);
    add_widgetl (op_dlg, FileLabel [0] = label_new (3, FCOPY_LABEL_X, fifteen, "fs-x-2"),
        XV_WLAY_NEXTROW);

    /* We will manage the dialog without any help, that's why
       we have to call init_dlg */
    init_dlg (op_dlg);
    op_dlg->running = 1;
    selected_button = FILE_SKIP;
    for (i = 0; i < 3; i++)
	last_percentage [i] = -99;
}

void
destroy_op_win (void)
{
#ifdef HAVE_XVIEW
    xtoolkit_kill_dialog (op_dlg);
#endif
    dlg_run_done (op_dlg);
    destroy_dlg (op_dlg);
#ifndef HAVE_X
    the_hint->widget.y = last_hint_line;
#endif
}

static int
show_no_bar (int n)
{
    if (n >= 0) {
    	label_set_text (ProgressLabel [n], "");
        gauge_show (ProgressGauge [n], 0);
    }
    return check_buttons ();
}

#ifndef HAVE_X
#define truncFileString(s) name_trunc (s, eta_extra + 47)
#else
#define truncFileString(s) s
#endif

static int
show_source (char *s)
{
    if (s != NULL){

#ifdef WITH_FULL_PATHS
    	int i = strlen (cpanel->cwd);

	/* We remove the full path we have added before */
        if (!strncmp (s, cpanel->cwd, i)){
            if (s[i] == PATH_SEP)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -