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

📄 file.c

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

    if (!do_append) {
       /* .ado: OS2 and NT don't have hardlinks */
#ifndef OS2_NT
        /* Check the hardlinks */
        if (!op_follow_links && sb.st_nlink > 1 &&
	     check_hardlinks (src_path, dst_path, &sb) == 1) {
    	    /* We have made a hardlink - no more processing is necessary */
    	    return return_status;
        }

        if (S_ISLNK (sb.st_mode))
	    return make_symlink (src_path, dst_path);

#endif /* !OS_NT */

        if (S_ISCHR (sb.st_mode) || S_ISBLK (sb.st_mode) || S_ISFIFO (sb.st_mode)
            || S_ISSOCK (sb.st_mode)){
        retry_mknod:
            if (mc_mknod (dst_path, sb.st_mode & umask_kill, sb.st_rdev) < 0){
	        return_status = file_error
		    (_(" Cannot create special file \"%s\" \n %s "), dst_path);
	        if (return_status == FILE_RETRY)
		    goto retry_mknod;
		return return_status;
	    }
	    /* Success */

#ifndef OS2_NT
	retry_mknod_uidgid:
	    if (preserve_uidgid && mc_chown (dst_path, sb.st_uid, sb.st_gid)){
		temp_status = file_error
		    (_(" Cannot chown target file \"%s\" \n %s "), dst_path);
		if (temp_status == FILE_RETRY)
		    goto retry_mknod_uidgid;
		return temp_status;
	    }
#endif
#ifndef __os2__
	retry_mknod_chmod:
	    if (preserve && mc_chmod (dst_path, sb.st_mode & umask_kill) < 0){
		temp_status = file_error (_(" Cannnot chmod target file \"%s\" \n %s "), dst_path);
		if (temp_status == FILE_RETRY)
		    goto retry_mknod_chmod;
		return temp_status;
	    }
#endif
	    return FILE_CONT;
        }
    }

    if (!do_append && !vfs_file_is_local (src_path) && vfs_file_is_local (dst_path)){
	mc_setctl (src_path, MCCTL_SETREMOTECOPY, dst_path);
    }
 retry_src_open:
    if ((source_desc = mc_open (src_path, O_RDONLY)) < 0){
	return_status = file_error
	    (_(" Cannot open source file \"%s\" \n %s "), src_path);
	if (return_status == FILE_RETRY)
	    goto retry_src_open;
	do_append = 0;
	return return_status;
    }

    resources |= 1;
    do_remote_copy = mc_ctl (source_desc, MCCTL_ISREMOTECOPY, 0);

    if (!do_remote_copy) {
 retry_src_fstat:
        if (mc_fstat (source_desc, &sb)){
	    return_status = file_error
	        (_(" Cannot fstat source file \"%s\" \n %s "), src_path);
	    if (return_status == FILE_RETRY)
	        goto retry_src_fstat;
	    do_append = 0;
            goto ret;
        }
#if 0
    /* Im not sure if we can delete this. sb is already filled by
    (*xstat)() - Norbert. */
    } else {
 retry_src_rstat:
        if (mc_stat (src_path, &sb)){
	    return_status = file_error
	        (_(" Cannot stat source file \"%s\" \n %s "), src_path);
	    if (return_status == FILE_RETRY)
	        goto retry_src_rstat;
	    do_append = 0;
            goto ret;
        }
#endif
    }
    src_mode = sb.st_mode;
#ifndef OS2_NT
    src_uid = sb.st_uid;
    src_gid = sb.st_gid;
#endif
    utb.actime = sb.st_atime;
    utb.modtime = sb.st_mtime;
    file_size = sb.st_size;

    /* Create the new regular file with small permissions initially,
       do not create a security hole.  */

    if (!do_remote_copy) {
 retry_dst_open:
        if ((do_append &&
            (dest_desc = mc_open (dst_path, O_WRONLY | O_APPEND)) < 0) ||
            (!do_append &&
            (dest_desc = mc_open (dst_path, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0)) {
	    return_status = file_error
	        (_(" Cannot create target file \"%s\" \n %s "), dst_path);
	    if (return_status == FILE_RETRY)
	        goto retry_dst_open;
	    do_append = 0;
	    goto ret;
        }
	resources |= 2; /* dst_path exists/dst_path opened */
	resources |= 4; /* remove short file */
    }
    appending = do_append;
    do_append = 0;

    if (!do_remote_copy) {
 retry_dst_fstat:
        /* Find out the optimal buffer size.  */
        if (mc_fstat (dest_desc, &sb)){
	    return_status = file_error
	        (_(" Cannot fstat target file \"%s\" \n %s "), dst_path);
	    if (return_status == FILE_RETRY)
	        goto retry_dst_fstat;
	    goto ret;
        }
        buf_size = 8*1024;

        buf = (char *) xmalloc (buf_size, "copy_file_file");
    }

    return_status = show_file_progress (0, file_size);
    mc_refresh ();
    if (return_status != FILE_CONT)
	goto ret;

    if (!do_remote_copy){
        for (;;){
    retry_src_read:
	    n_read = mc_read (source_desc, buf, buf_size);
	    if (n_read < 0){
	        return_status = file_error
		    (_(" Cannot read source file \"%s\" \n %s "), src_path);
	        if (return_status == FILE_RETRY)
		    goto retry_src_read;
	        goto ret;
	    }
	    if (n_read == 0)
	        break;

	    n_read_total += n_read;

    retry_dst_write:
	    n_written = mc_write (dest_desc, buf, n_read);
	    if (n_written < n_read){
	        return_status = file_error
		    (_(" Cannot write target file \"%s\" \n %s "), dst_path);
	        if (return_status == FILE_RETRY)
		    goto retry_dst_write;
	        goto ret;
	    }
	    return_status = show_file_progress (n_read_total, file_size);
	    mc_refresh ();
	    if (return_status != FILE_CONT)
	        goto ret;
        }
    } else {
	struct timeval tv_current;
	struct timeval tv_transfer_start;
	struct timeval tv_last_update;
	struct timeval tv_last_input;
        int    i, size, secs, update_secs;
	long   dt;
	char   *stalled_msg;

	gettimeofday (&tv_transfer_start, (struct timezone *) NULL);
	tv_last_update = tv_transfer_start;
	eta_secs = 0.0;

        for (i = 1; i;) {
            switch (size = mc_ctl (source_desc, MCCTL_REMOTECOPYCHUNK, 8192)) {
                case MCERR_TARGETOPEN:
		    message_1s (1, MSG_ERROR, _(" Can't open target file "));
		    goto ret;
                case MCERR_READ:
		    goto ret;
                case MCERR_WRITE:
		    message_1s (1, MSG_ERROR, _(" Can't write to local target file "));
		    goto ret;
	        case MCERR_DATA_ON_STDIN:
		    break;
                case MCERR_FINISH:
                    resources |= 8;
                    i = 0;
                    break;
            }

            /* the first time we reach this line the target file has been created
	       or truncated and we actually have a short target file.
	       Do we really want to delete the target file when the ftp transfer
	       fails? If we don't delete it we would be able to use reget later.
               (Norbert) */
	    resources |= 4; /* remove short file */

	    if (i && size != MCERR_DATA_ON_STDIN){
		n_read_total += size;

		/* Windows NT ftp servers report that files have no
		 * permissions: -------, so if we happen to have actually
		 * read something, we should fix the permissions.
		 */
		if (!(src_mode &
		      ((S_IRUSR|S_IWUSR|S_IXUSR)    /* user */
		       |(S_IXOTH|S_IWOTH|S_IROTH)  /* other */
		       |(S_IXGRP|S_IWGRP|S_IRGRP)))) /* group */
		    src_mode = S_IRUSR|S_IWUSR|S_IROTH|S_IRGRP;

		gettimeofday (&tv_last_input, NULL);
	    }
	    /* Timed operations: */
	    gettimeofday (&tv_current, NULL);

	    /* 1. Update rotating dash after some time (hardcoded to 2 seconds) */
	    secs = (tv_current.tv_sec - tv_last_update.tv_sec);
	    if (secs > 2){
		rotate_dash ();
		tv_last_update = tv_current;
	    }

	    /* 2. Check for a stalled condition */
	    update_secs = (tv_current.tv_sec - tv_last_input.tv_sec);
	    stalled_msg = "";
	    if (update_secs > 4){
		stalled_msg = _("(stalled)");
	    }

	    /* 3. Compute ETA */
	    if (secs > 2 || eta_secs == 0.0){
		dt = (tv_current.tv_sec - tv_transfer_start.tv_sec);

		if (n_read_total){
		    eta_secs = ((dt / (double) n_read_total) * file_size) - dt;
		    bps = n_read_total / ((dt < 1) ? 1 : dt);
		} else
		    eta_secs = 0.0;
	    }

	    /* 4. Compute BPS rate */
	    if (secs > 2){
		bps_time = (tv_current.tv_sec - tv_transfer_start.tv_sec);
		if (bps_time < 1)
		    bps_time = 1;
		bps = n_read_total / bps_time;
	    }

	    label_set_text (stalled_label, stalled_msg);

	    return_status = show_file_progress (n_read_total, file_size);
	    mc_refresh ();
	    if (return_status != FILE_CONT)
	        goto ret;
        }
    }
    resources &= ~4; /* copy successful, don't remove target file */

ret:
    if (buf)
	free (buf);

 retry_src_close:
    if ((resources & 1) && mc_close (source_desc) < 0){
	temp_status = file_error
	    (_(" Cannot close source file \"%s\" \n %s "), src_path);
	if (temp_status == FILE_RETRY)
	    goto retry_src_close;
	if (temp_status == FILE_ABORT)
	    return_status = temp_status;
    }

 retry_dst_close:
    if ((resources & 2) && mc_close (dest_desc) < 0){
	temp_status = file_error
	    (_(" Cannot close target file \"%s\" \n %s "), dst_path);
	if (temp_status == FILE_RETRY)
	    goto retry_dst_close;
	return_status = temp_status;
    }

    if (resources & 4) {
        /* Remove short file */
	mc_unlink (dst_path);
	if (do_remote_copy) {
    	    mc_ctl (source_desc, MCCTL_FINISHREMOTE, -1);
	}
    } else if (resources & (2|8)) {
        /* no short file and destination file exists */
#ifndef OS2_NT
	if (!appending && preserve_uidgid) {
         retry_dst_chown:
    	    if (mc_chown (dst_path, src_uid, src_gid)){
		temp_status = file_error
	    	    (_(" Cannot chown target file \"%s\" \n %s "), dst_path);
		if (temp_status == FILE_RETRY)
	    	    goto retry_dst_chown;
		return_status = temp_status;
    	    }
	}
#endif

     /* .ado: according to the XPG4 standard, the file must be closed before
      * chmod can be invoked
      */
     retry_dst_chmod:
	if (!appending && mc_chmod (dst_path, src_mode & umask_kill)){
	    temp_status = file_error
		(_(" Cannot chmod target file \"%s\" \n %s "), dst_path);
	    if (temp_status == FILE_RETRY)
		goto retry_dst_chmod;
	    return_status = temp_status;
	}

	if (!appending && preserve)
	    mc_utime (dst_path, &utb);
    }
    return return_status;
}

/*
 * I think these copy_*_* functions should have a return type.
 * anyway, this function *must* have two directories as arguments.
 */
/* FIXME: This function needs to check the return values of the
   function calls */
int
copy_dir_dir (char *s, char *d, int toplevel, int move_over, int delete,
              struct link *parent_dirs)
{
#ifdef __os2__
    DIR    *next;
#else
    struct dirent *next;
#endif
    struct stat   buf, cbuf;
    DIR    *reading;
    char   *path, *mdpath, *dest_file, *dest_dir;
    int    return_status = FILE_CONT;
    struct utimbuf utb;
    struct link *lp;

    /* First get the mode of the source dir */
 retry_src_stat:
    if ((*xstat) (s, &cbuf)){
	return_status = file_error (_(" Cannot stat source directory \"%s\" \n %s "), s);
	if (return_status == FILE_RETRY)
	    goto retry_src_stat;
	return return_status;
    }

    if (is_in_linklist (dest_dirs, s, &cbuf)) {
	/* Don't copy a directory we created before (we don't want to copy
	   infinitely if a directory is copied into itself) */
	/* FIXME: should there be an error message and FILE_SKIP? - Norbert */
	return FILE_CONT;
    }

/* Hmm, hardlink to directory??? - Norbert */
/* FIXME: In this step we should do something
   in case the destination already exist */
    /* Check the hardlinks */
    if (preserve && cbuf.st_nlink > 1 && check_hardlinks (s, d, &cbuf) == 1) {
    	/* We have made a hardlink - no more processing is necessary */
    	return return_status;
    }

    if (!S_ISDIR (cbuf.st_mode)){
	return_status = file_error (_(" Source directory \"%s\" is not a directory \n %s "), s);
	if (return_status == FILE_RETRY)
	    goto retry_src_stat;
	return return_status;
    }

#ifndef OS2_NT
    if (is_in_linklist (parent_dirs, s, &cbuf)) {
 	/* we found a cyclic symbolic link */
	   message_2s (1, MSG_ERROR, _(" Cannot copy cyclic symbolic link \n `%s' "), s);
	return FILE_SKIP;
    }
#endif

    lp = xmalloc (sizeof (struct link), "parent_dirs");
    lp->vfs = vfs_type (s);
    lp->ino = cbuf.st_ino;
    lp->dev = cbuf.st_dev;
    lp->next = parent_dirs;
    parent_dirs = lp;

    /* Now, check if the dest dir exists, if not, create it. */
    if (mc_stat (d, &buf)){
    	/* Here the dir doesn't exist : make it !*/

    	if (move_over) {
            if (mc_rename (s, d) == 0) {
		free (parent_dirs);
		return FILE_CONT;
	    }
	}
	dest_dir = copy_strings (d, 0);
    } else {
        /*
         * If the destination directory exists, we want to copy the whole
         * directory, but we only want this to happen once.
	 *
	 * Escape sequences added to the * to avoid compiler warnings.
         * so, say /bla exists, if we copy /tmp/\* to /bla, we get /bla/tmp/\*
         * or ( /bla doesn't exist )       /tmp/\* to /bla     ->  /bla/\*
         */
#if 1
/* Again, I'm getting curious. Is not d already what we wanted, incl.
 *  masked source basename? Is not this just a relict of the past versions?
 *  I'm afraid this will lead into a two level deep dive :(
 *
 * I think this is indeed the problem.  I can not remember any case where
 * we actually would like that behaviour -miguel
 *
 * It's a documented feature (option `Dive into subdir if exists' in the
 * copy/move dialog). -Norbert
 */
        if (toplevel && dive_into_subdirs){
	    dest_dir = concat_dir_and_file (d, x_basename (s));
	} else
#endif
	{
	    dest_dir = copy_strings (d, 0);
	    goto dont_mkdir;
	}
    }
 retry_dst_mkdir:
    if (my_mkdir (dest_dir, (cbuf.st_mode & umask_kill) | S_IRWXU)){
	return_status = file_error (_(" Cannot create target directory \"%s\" \n %s "), dest_dir);
	if (return_status == FILE_RETRY)
	    goto retry_dst_mkdir;
	goto ret;
    }

    lp = xmalloc (sizeof (struct link), "dest_dirs");
    mc_stat (dest_dir, &buf);
    lp->vfs = vfs_type (dest_dir);
    lp->ino = buf.st_ino;
    lp->dev = buf.st_dev;
    lp->next = dest_dirs;
    dest_dirs = lp;

#ifndef OS2_NT
    if (preserve_uidgid) {
     retry_dst_chown:
        if (mc_chown (dest_dir, cbuf.st_uid, cbuf.st_gid)){
	    return_status = file_error
	        (_(" Cannot chown target directory \"%s\" \n %s "), dest_dir);
	    if (return_status == FILE_RETRY)
	        goto retry_dst_chown;
	    goto ret;
        }
    }
#endif

 dont_mkdir:
    /* open the source dir for reading */
    if ((reading = mc_opendir (s)) == 0){
	goto ret;
    }

⌨️ 快捷键说明

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