예제 #1
0
static int shift_ll(LIKELIHOOD **** ll_pym,
		    struct Region *region, int block_size)
{
    static int first = 1;
    static int xoffset[20];
    static int yoffset[20];

    int xdelta;
    int ystart, ystop, ydelta;
    int D;
    int k, i;
    int block_size_k;
    struct Region region_buff;

    /* if first time, set offsets to 0 */
    if (first) {
	D = levels(block_size, block_size);
	for (k = 0; k <= D; k++)
	    xoffset[k] = yoffset[k] = 0;
	first = 0;
    }

    /* save region information */
    copy_reg(region, &region_buff);

    /* subtract pointer offsets for each scale */
    D = levels(block_size, block_size);
    block_size_k = block_size;
    for (k = 0; k <= D; k++) {
	xdelta = region->xmin - xoffset[k];
	ydelta = region->ymin - yoffset[k];
	xoffset[k] = region->xmin;
	yoffset[k] = region->ymin;

	ystart = region->ymin;
	ystop = ystart + block_size_k;

	ll_pym[k] -= ydelta;
	for (i = ystart; i < ystop; i++)
	    ll_pym[k][i] -= xdelta;
	dec_reg(region);
	block_size_k = block_size_k / 2;
    }

    /* replace region information */
    copy_reg(&region_buff, region);

    return 0;
}
예제 #2
0
state_ptr copy_state(state_ptr s) {
    state_ptr result = (state_ptr) malloc(sizeof(state_rec));
    result->pc = s->pc;
    result->r = copy_reg(s->r);
    result->m = copy_mem(s->m);
    result->cc = s->cc;
    return result;
}
int main(int argc, char *argv[])
{
    FILE *code_file;
    int max_steps = 10000;

    // edit by leo
    init_sharemem();
    // edit end
	

    state_ptr s = new_state(MEM_SIZE);
    
    mem_t saver = copy_reg(s->r);
    mem_t savem;
    int step = 0;

    stat_t e = STAT_AOK;

    if (argc < 2 || argc > 3)
	usage(argv[0]);
    code_file = fopen(argv[1], "r");
    if (!code_file) {
	fprintf(stderr, "Can't open code file '%s'\n", argv[1]);
	exit(1);
    }
    
    if (!load_mem(s->m, code_file, 1)) {
	printf("Exiting\n");
	return 1;
    }    
    savem = copy_mem(s->m);
  
    // edit by leo
    // printf("error happen after here!\n");
    // edit end
    if (argc > 2)
	max_steps = atoi(argv[2]);

    for (step = 0; step < max_steps && e == STAT_AOK; step++)
	e = step_state(s, stdout);
    
    
    printf("Stopped in %d steps at PC = 0x%x.  Status '%s', CC %s\n",
	   step, s->pc, stat_name(e), cc_name(s->cc));

    printf("Changes to registers:\n");
    diff_reg(saver, s->r, stdout);

    printf("\nChanges to memory:\n");
    diff_mem(savem, s->m, stdout);

    free_state(s);
    free_reg(saver);
    free_mem(savem);

    return 0;
}
예제 #4
0
int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname)
{
	int result;

	START_PROFILE(syscall_rename);
	result = rename(oldname, newname);
	if (errno == EXDEV) {
		/* Rename across filesystems needed. */
		result = copy_reg(oldname, newname);
	}

	END_PROFILE(syscall_rename);
	return result;
}
예제 #5
0
int main(int argc, char *argv[])
{
    FILE *code_file;
    int max_steps = 10000;

    state_ptr s = new_state(MEM_SIZE);
    mem_t saver = copy_reg(s->r);
    mem_t savem;
    int step = 0;

    exc_t e = EXC_NONE;

    if (argc < 2 || argc > 3)
	usage(argv[0]);
    code_file = fopen(argv[1], "r");
    if (!code_file) {
	fprintf(stderr, "Can't open code file '%s'\n", argv[1]);
	exit(1);
    }

    if (!load_mem(s->m, code_file, 1)) {
	printf("Exiting\n");
	return 1;
    }

    savem = copy_mem(s->m);
  
    if (argc > 2)
	max_steps = atoi(argv[2]);

    for (step = 0; step < max_steps && e == EXC_NONE; step++)
	e = step_state(s, stdout);

    printf("Stopped in %d steps at PC = 0x%x.  Exception '%s', CC %s\n",
	   step, s->pc, exc_name(e), cc_name(s->cc));

    printf("Changes to registers:\n");
    diff_reg(saver, s->r, stdout);

    printf("\nChanges to memory:\n");
    diff_mem(savem, s->m, stdout);

    free_state(s);
    free_reg(saver);
    free_mem(savem);

    return 0;
}
예제 #6
0
파일: doscalls.c 프로젝트: AllardJ/Tomato
int dos_rename(char *from, char *to)
{
    int rcode;  
    pstring zfrom, zto;

    pstrcpy (zfrom, dos_to_unix (from, False));
    pstrcpy (zto, dos_to_unix (to, False));
    rcode = rename (zfrom, zto);

    if (errno == EXDEV) 
    {
      /* Rename across filesystems needed. */
      rcode = copy_reg (zfrom, zto);        
    }
    return rcode;
}
예제 #7
0
static int crossrename_rename(vfs_handle_struct *handle,
			  const struct smb_filename *smb_fname_src,
			  const struct smb_filename *smb_fname_dst)
{
	int result = -1;

	START_PROFILE(syscall_rename);

	if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
		errno = ENOENT;
		goto out;
	}

	result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
	if ((result == -1) && (errno == EXDEV)) {
		/* Rename across filesystems needed. */
		result = copy_reg(smb_fname_src->base_name,
				  smb_fname_dst->base_name);
	}

 out:
	END_PROFILE(syscall_rename);
	return result;
}
예제 #8
0
static void seq_MAP_routine(unsigned char ***sf_pym,	/* pyramid of segmentations */
			    struct Region *region,	/* specifies image subregion */
			    LIKELIHOOD **** ll_pym,	/* pyramid of class statistics */
			    int M,	/* number of classes */
			    double *alpha_dec	/* decimation parameters returned by seq_MAP */
    )
{
    int j, k;			/* loop index */
    int wd, ht;			/* width and height at each resolution */
    int *period;		/* sampling period at each resolution */
    int D;			/* number of resolutions -1 */
    double ***N;		/* transition probability statistics; N[2][3][2] */
    double alpha[3];		/* transition probability parameters */
    double tmp[3];		/* temporary transition probability parameters */
    double diff1;		/* change in parameter estimates */
    double diff2;		/* change in log likelihood */
    struct Region *regionary;	/* array of region stuctures */

    /* determine number of resolutions */
    D = levels_reg(region);

    /* allocate memory */
    if ((N = (double ***)multialloc(sizeof(double), 3, 2, 3, 2)) == NULL)
	G_fatal_error(_("Unable to allocate memory"));

    regionary = (struct Region *)G_malloc((D + 1) * sizeof(struct Region));
    period = (int *)G_malloc(D * sizeof(int));

    /* Compute the image region at each resolution.       */
    k = 0;
    copy_reg(region, &(regionary[k]));
    reg_to_wdht(&(regionary[k]), &wd, &ht);
    while ((wd > 2) && (ht > 2)) {
	copy_reg(&(regionary[k]), &(regionary[k + 1]));
	dec_reg(&(regionary[k + 1]));
	reg_to_wdht(&(regionary[k + 1]), &wd, &ht);
	k++;
    }

    /* Compute sampling period for EM algorithm at each resolution. */
    for (k = 0; k < D; k++) {
	period[k] = (int)pow(2.0, (D - k - 2) / 2.0);
	if (period[k] < 1)
	    period[k] = 1;
    }

    /* Compute Maximum Likelihood estimate at coarsest resolution */
    MLE(sf_pym[D], ll_pym[D], &(regionary[D]), M);

    /* Initialize the transition parameters */
    alpha[0] = 0.5 * (3.0 / 7.0);
    alpha[1] = 0.5 * (2.0 / 7.0);
    alpha[2] = 0.0;

    /* Interpolate the classification at each resolution */
    for (D--; D >= 0; D--) {
	G_debug(1, "Resolution = %d; period = %d", D, period[D]);

	for (j = 0; j < 3; j++)
	    alpha[j] *= (1 - EM_PRECISION * 10);
	print_alpha(alpha);
	/* Apply EM algorithm to estimate alpha. Continue for *
	 * fixed number of iterations or until convergence.   */
	do {
	    interp(sf_pym[D], &(regionary[D]), sf_pym[D + 1], ll_pym[D], M,
		   alpha, period[D], N, 1);
	    print_N(N);
	    G_debug(4, "log likelihood = %f", log_like(N, alpha, M));
	    for (j = 0; j < 3; j++)
		tmp[j] = alpha[j];

	    alpha_max(N, alpha, M, ML_PRECISION);
	    print_alpha(alpha);
	    G_debug(4, "log likelihood = %f", log_like(N, alpha, M));

	    for (diff1 = j = 0; j < 3; j++)
		diff1 += fabs(tmp[j] - alpha[j]);
	    diff2 = log_like(N, alpha, M) - log_like(N, tmp, M);
	} while ((diff1 > EM_PRECISION) && (diff2 > 0));
	interp(sf_pym[D], &(regionary[D]), sf_pym[D + 1], ll_pym[D], M, alpha,
	       1, N, 0);
	alpha_dec[D] = alpha_dec_max(N);

	print_N(N);
	alpha_max(N, alpha, M, ML_PRECISION);
	print_alpha(alpha);
    }

    /* free up N */
    G_free((char *)regionary);
    G_free((char *)period);
    multifree((char *)N, 3);
}
예제 #9
0
/* 
 * run_tty_sim - Run the simulator in TTY mode
 */
static void run_tty_sim() 
{
    int icount = 0;
    byte_t run_status = STAT_AOK;
    cc_t result_cc = 0;
    int byte_cnt = 0;
    mem_t mem0, reg0;
    state_ptr isa_state = NULL;


    /* In TTY mode, the default object file comes from stdin */
    if (!object_file) {
        object_file = stdin;
    }

    if (verbosity >= 2)
        sim_set_dumpfile(stdout);
    sim_init();

    /* Emit simulator name */
    if (verbosity >= 2)
        printf("%s\n", simname);

    byte_cnt = load_mem(mem, object_file, 1, START_PLACE);
    if (byte_cnt == 0) {
        fprintf(stderr, "No lines of code found\n");
        exit(1);
    } else if (verbosity >= 2) {
        printf("%d bytes of code read\n", byte_cnt);
    }
    fclose(object_file);
    if (do_check) {
        isa_state = new_state(0);
        free_reg(isa_state->r);
        free_mem(isa_state->m);
        isa_state->m = copy_mem(mem);
        isa_state->r = copy_reg(reg);
        isa_state->cc = cc;
    }

    if(verbosity > 0){
        mem0 = copy_mem(mem);
        reg0 = copy_reg(reg);
    }

    icount = sim_run_pipe(instr_limit, 5*instr_limit, &run_status, &result_cc);
    if (verbosity > 0) {
        printf("%d instructions executed\n", icount);
        printf("Status = %s\n", stat_name(run_status));
        printf("Condition Codes: %s\n", cc_name(result_cc));
        printf("Changed Register State:\n");
        diff_reg(reg0, reg, stdout);
        printf("Changed Memory State:\n");
        diff_mem(mem0, mem, stdout);
    }
    if (do_check) {
        exit(0);
        byte_t e = STAT_AOK;
        int step;
        bool_t match = TRUE;

        for (step = 0; step < instr_limit && e == STAT_AOK; step++) {
            e = step_state(isa_state, stdout);
        }

        if (diff_reg(isa_state->r, reg, NULL)) {
            match = FALSE;
            if (verbosity > 0) {
                printf("ISA Register != Pipeline Register File\n");
                diff_reg(isa_state->r, reg, stdout);
            }
        }
        if (diff_mem(isa_state->m, mem, NULL)) {
            match = FALSE;
            if (verbosity > 0) {
                printf("ISA Memory != Pipeline Memory\n");
                diff_mem(isa_state->m, mem, stdout);
            }
        }
        if (isa_state->cc != result_cc) {
            match = FALSE;
            if (verbosity > 0) {
                printf("ISA Cond. Codes (%s) != Pipeline Cond. Codes (%s)\n",
                        cc_name(isa_state->cc), cc_name(result_cc));
            }
        }
        if (match) {
            printf("ISA Check Succeeds\n");
        } else {
            printf("ISA Check Fails\n");
        }
    }

    /* Emit CPI statistics */
    {
        double cpi = instructions > 0 ? (double) cycles/instructions : 1.0;
        printf("%d CPI: %d cycles/%d instructions = %.2f\n", PSIM_ID,
                cycles, instructions, cpi);
    }
}
예제 #10
0
파일: throw.c 프로젝트: BillTheBest/k42
static void *
throw_helper(struct eh_context *eh, void *pc,
	     frame_state *my_udata, long *offset_p)
{
    frame_state ustruct2, *udata = &ustruct2;
    frame_state ustruct;
    frame_state *sub_udata = &ustruct;
    void *saved_pc = pc;
    void *handler;
    void *handler_p = NULL;
    void *pc_p = NULL;
    frame_state saved_ustruct;
    int new_eh_model;
    int cleanup = 0;
    int only_cleanup = 0;
    int rethrow = 0;
    int saved_state = 0;
    long args_size;
    __eh_info *eh_info = (__eh_info *)eh->info;

    if (eh->table_index != (void *) 0) {
	rethrow = 1;
    }
    memcpy(udata, my_udata, sizeof (*udata));

    handler = (void *) 0;
    for (;;) {
	frame_state *p = udata;
	udata = next_stack_level (pc, udata, sub_udata);
	sub_udata = p;

	if (! udata) {
	    break;
	}

	if (udata->eh_ptr == ((void *)0) ) {
	    new_eh_model = 0;
	} else {
	    new_eh_model = (((exception_descriptor *)(udata->eh_ptr))->
			    runtime_id_field == ((void *) -2) );
	}

	if (rethrow) {
	    rethrow = 0;
	    handler = find_exception_handler (eh->table_index, udata->eh_ptr,
					      eh_info, 1, &cleanup);
	    eh->table_index = (void *)0;
        } else {
	    if (new_eh_model) {
		handler = find_exception_handler (pc, udata->eh_ptr, eh_info,
						  0, &cleanup);
	    } else {
		handler = old_find_exception_handler (pc, udata->eh_ptr);
	    }
	}

	if (handler) {
	    if (cleanup) {
		if (!saved_state) {
		    saved_ustruct = *udata;
		    handler_p = handler;
		    pc_p = pc;
		    saved_state = 1;
		    only_cleanup = 1;
		}
	    } else {
		only_cleanup = 0;
		break;
	    }
	}
	pc = get_return_addr (udata, sub_udata) - 1;
    }

    if (saved_state) {
	udata = &saved_ustruct;
	handler = handler_p;
	pc = pc_p;
	if (only_cleanup) {
	    __unwinding_cleanup ();
	}
    }

    if (! handler) {
	__terminate();
    }
    eh->handler_label = handler;

    args_size = udata->args_size;

    if (pc == saved_pc) {
        udata = my_udata;
    } else {
	int i;
	void *handler_pc = pc;

	pc = saved_pc;
	memcpy (udata, my_udata, sizeof (*udata));

	while (pc != handler_pc) {
	    frame_state *p = udata;
	    udata = next_stack_level (pc, udata, sub_udata);
	    sub_udata = p;

	    for (i = 0; i < 76 ; ++i) {
		if (i != udata->retaddr_column && udata->saved[i]) {
		    if (in_reg_window (i, udata)
			&& udata->saved[udata->retaddr_column] == 2
			&& udata->reg_or_offset[udata->retaddr_column] == i) {
			continue;
		    }
		    copy_reg (i, udata, my_udata);
		}
	    }
	    pc = get_return_addr (udata, sub_udata) - 1;
	}

	if (udata->saved[udata->retaddr_column] == 2 ) {
	    i = udata->reg_or_offset[udata->retaddr_column];
	    if (in_reg_window (i, udata)) {
		copy_reg (i, udata, my_udata);
	    }
	}
    }
    *offset_p = udata->cfa - my_udata->cfa + args_size;
    return handler;
}
예제 #11
0
파일: copy.c 프로젝트: brokendragon/PERDICE
static int
copy_internal (const char *src_path, const char *dst_path,
	       int new_dst,
	       dev_t device,
	       struct dir_list *ancestors,
	       const struct cp_options *x,
	       int command_line_arg,
	       int *copy_into_self,
	       int *rename_succeeded)
{
  struct stat src_sb;
  struct stat dst_sb;
  mode_t src_mode;
  mode_t src_type;
  char *earlier_file = NULL;
  char *dst_backup = NULL;
  int backup_succeeded = 0;
  int delayed_fail;
  int copied_as_regular = 0;
  int ran_chown = 0;
  int preserve_metadata;

  if (x->move_mode && rename_succeeded)
    *rename_succeeded = 0;

  *copy_into_self = 0;
  if ((*(x->xstat)) (src_path, &src_sb))
    {
      error (0, errno, _("cannot stat %s"), quote (src_path));
      return 1;
    }

  src_type = src_sb.st_mode;

  src_mode = src_sb.st_mode;

  if (S_ISDIR (src_type) && !x->recursive)
    {
      error (0, 0, _("omitting directory %s"), quote (src_path));
      return 1;
    }

  /* Detect the case in which the same source file appears more than
     once on the command line and no backup option has been selected.
     If so, simply warn and don't copy it the second time.
     This check is enabled only if x->src_info is non-NULL.  */
  if (command_line_arg)
    {
      if ( ! S_ISDIR (src_sb.st_mode)
	   && x->backup_type == none
	   && seen_file (x->src_info, src_path, &src_sb))
	{
	  error (0, 0, _("warning: source file %s specified more than once"),
		 quote (src_path));
	  return 0;
	}

      record_file (x->src_info, src_path, &src_sb);
    }

  if (!new_dst)
    {
      if ((*(x->xstat)) (dst_path, &dst_sb))
	{
	  if (errno != ENOENT)
	    {
	      error (0, errno, _("cannot stat %s"), quote (dst_path));
	      return 1;
	    }
	  else
	    {
	      new_dst = 1;
	    }
	}
      else
	{
	  int return_now;
	  int ok = same_file_ok (src_path, &src_sb, dst_path, &dst_sb,
				 x, &return_now);
	  if (return_now)
	    return 0;

	  if (! ok)
	    {
	      error (0, 0, _("%s and %s are the same file"),
		     quote_n (0, src_path), quote_n (1, dst_path));
	      return 1;
	    }

	  if (!S_ISDIR (dst_sb.st_mode))
	    {
	      if (S_ISDIR (src_type))
		{
		  error (0, 0,
		     _("cannot overwrite non-directory %s with directory %s"),
			 quote_n (0, dst_path), quote_n (1, src_path));
		  return 1;
		}

	      /* Don't let the user destroy their data, even if they try hard:
		 This mv command must fail (likewise for cp):
		   rm -rf a b c; mkdir a b c; touch a/f b/f; mv a/f b/f c
		 Otherwise, the contents of b/f would be lost.
		 In the case of `cp', b/f would be lost if the user simulated
		 a move using cp and rm.
		 Note that it works fine if you use --backup=numbered.  */
	      if (command_line_arg
		  && x->backup_type != numbered
		  && seen_file (x->dest_info, dst_path, &dst_sb))
		{
		  error (0, 0,
			 _("will not overwrite just-created %s with %s"),
			 quote_n (0, dst_path), quote_n (1, src_path));
		  return 1;
		}
	    }

	  if (!S_ISDIR (src_type))
	    {
	      if (S_ISDIR (dst_sb.st_mode))
		{
		  error (0, 0,
		       _("cannot overwrite directory %s with non-directory"),
			 quote (dst_path));
		  return 1;
		}

	      if (x->update && MTIME_CMP (src_sb, dst_sb) <= 0)
		{
		  /* We're using --update and the source file is older
		     than the destination file, so there is no need to
		     copy or move.  */
		  /* Pretend the rename succeeded, so the caller (mv)
		     doesn't end up removing the source file.  */
		  if (rename_succeeded)
		    *rename_succeeded = 1;
		  return 0;
		}
	    }

	  /* When there is an existing destination file, we may end up
	     returning early, and hence not copying/moving the file.
	     This may be due to an interactive `negative' reply to the
	     prompt about the existing file.  It may also be due to the
	     use of the --reply=no option.  */
	  if (!S_ISDIR (src_type))
	    {
	      /* cp and mv treat -i and -f differently.  */
	      if (x->move_mode)
		{
		  if ((x->interactive == I_ALWAYS_NO
		       && UNWRITABLE (dst_path, dst_sb.st_mode))
		      || ((x->interactive == I_ASK_USER
			   || (x->interactive == I_UNSPECIFIED
			       && x->stdin_tty
			       && UNWRITABLE (dst_path, dst_sb.st_mode)))
			  && (overwrite_prompt (dst_path, &dst_sb), 1)
			  && ! yesno ()))
		    {
		      /* Pretend the rename succeeded, so the caller (mv)
			 doesn't end up removing the source file.  */
		      if (rename_succeeded)
			*rename_succeeded = 1;
		      return 0;
		    }
		}
	      else
		{
		  if (x->interactive == I_ALWAYS_NO
		      || (x->interactive == I_ASK_USER
			  && (overwrite_prompt (dst_path, &dst_sb), 1)
			  && ! yesno ()))
		    {
		      return 0;
		    }
		}
	    }

	  if (x->move_mode)
	    {
	      /* In move_mode, DEST may not be an existing directory.  */
	      if (S_ISDIR (dst_sb.st_mode))
		{
		  error (0, 0, _("cannot overwrite directory %s"),
			 quote (dst_path));
		  return 1;
		}

	      /* Don't allow user to move a directory onto a non-directory.  */
	      if (S_ISDIR (src_sb.st_mode) && !S_ISDIR (dst_sb.st_mode))
		{
		  error (0, 0,
		       _("cannot move directory onto non-directory: %s -> %s"),
			 quote_n (0, src_path), quote_n (0, dst_path));
		  return 1;
		}
	    }

	  if (x->backup_type != none && !S_ISDIR (dst_sb.st_mode))
	    {
	      char *tmp_backup = find_backup_file_name (dst_path,
							x->backup_type);
	      if (tmp_backup == NULL)
		xalloc_die ();

	      /* Detect (and fail) when creating the backup file would
		 destroy the source file.  Before, running the commands
		 cd /tmp; rm -f a a~; : > a; echo A > a~; cp --b=simple a~ a
		 would leave two zero-length files: a and a~.  */
	      /* FIXME: but simply change e.g., the final a~ to `./a~'
		 and the source will still be destroyed.  */
	      if (STREQ (tmp_backup, src_path))
		{
		  const char *fmt;
		  fmt = (x->move_mode
		 ? _("backing up %s would destroy source;  %s not moved")
		 : _("backing up %s would destroy source;  %s not copied"));
		  error (0, 0, fmt,
			 quote_n (0, dst_path),
			 quote_n (1, src_path));
		  free (tmp_backup);
		  return 1;
		}

	      dst_backup = (char *) alloca (strlen (tmp_backup) + 1);
	      strcpy (dst_backup, tmp_backup);
	      free (tmp_backup);
	      if (rename (dst_path, dst_backup))
		{
		  if (errno != ENOENT)
		    {
		      error (0, errno, _("cannot backup %s"), quote (dst_path));
		      return 1;
		    }
		  else
		    {
		      dst_backup = NULL;
		    }
		}
	      else
		{
		  backup_succeeded = 1;
		}
	      new_dst = 1;
	    }
	  else if (! S_ISDIR (dst_sb.st_mode)
		   && (x->unlink_dest_before_opening
		       || (x->xstat == lstat
			   && ! S_ISREG (src_sb.st_mode))))
	    {
	      if (unlink (dst_path) && errno != ENOENT)
		{
		  error (0, errno, _("cannot remove %s"), quote (dst_path));
		  return 1;
		}
	      new_dst = 1;
	    }
	}
    }

  /* If the source is a directory, we don't always create the destination
     directory.  So --verbose should not announce anything until we're
     sure we'll create a directory. */
  if (x->verbose && !S_ISDIR (src_type))
    {
      printf ("%s -> %s", quote_n (0, src_path), quote_n (1, dst_path));
      if (backup_succeeded)
	printf (_(" (backup: %s)"), quote (dst_backup));
      putchar ('\n');
    }

  /* Associate the destination path with the source device and inode
     so that if we encounter a matching dev/ino pair in the source tree
     we can arrange to create a hard link between the corresponding names
     in the destination tree.

     Sometimes, when preserving links, we have to record dev/ino even
     though st_nlink == 1:
     - when using -H and processing a command line argument;
	that command line argument could be a symlink pointing to another
	command line argument.  With `cp -H --preserve=link', we hard-link
	those two destination files.
     - likewise for -L except that it applies to all files, not just
	command line arguments.

     Also record directory dev/ino when using --recursive.  We'll use that
     info to detect this problem: cp -R dir dir.  FIXME-maybe: ideally,
     directory info would be recorded in a separate hash table, since
     such entries are useful only while a single command line hierarchy
     is being copied -- so that separate table could be cleared between
     command line args.  Using the same hash table to preserve hard
     links means that it may not be cleared.  */

  if ((x->preserve_links
       && (1 < src_sb.st_nlink
	   || (command_line_arg
	       && x->dereference == DEREF_COMMAND_LINE_ARGUMENTS)
	   || x->dereference == DEREF_ALWAYS))
      || (x->recursive && S_ISDIR (src_type)))
    {
      earlier_file = remember_copied (dst_path, src_sb.st_ino, src_sb.st_dev);
    }

  /* Did we copy this inode somewhere else (in this command line argument)
     and therefore this is a second hard link to the inode?  */

  if (earlier_file)
    {
      /* Avoid damaging the destination filesystem by refusing to preserve
	 hard-linked directories (which are found at least in Netapp snapshot
	 directories).  */
      if (S_ISDIR (src_type))
	{
	  /* If src_path and earlier_file refer to the same directory entry,
	     then warn about copying a directory into itself.  */
	  if (same_name (src_path, earlier_file))
	    {
	      error (0, 0, _("cannot copy a directory, %s, into itself, %s"),
		     quote_n (0, top_level_src_path),
		     quote_n (1, top_level_dst_path));
	      *copy_into_self = 1;
	    }
	  else
	    {
	      error (0, 0, _("will not create hard link %s to directory %s"),
		     quote_n (0, dst_path), quote_n (1, earlier_file));
	    }

	  goto un_backup;
	}

      {
	int link_failed;

	link_failed = link (earlier_file, dst_path);

	/* If the link failed because of an existing destination,
	   remove that file and then call link again.  */
	if (link_failed && errno == EEXIST)
	  {
	    if (unlink (dst_path))
	      {
		error (0, errno, _("cannot remove %s"), quote (dst_path));
		goto un_backup;
	      }
	    link_failed = link (earlier_file, dst_path);
	  }

	if (link_failed)
	  {
	    error (0, errno, _("cannot create hard link %s to %s"),
		   quote_n (0, dst_path), quote_n (1, earlier_file));
	    goto un_backup;
	  }

	return 0;
      }
    }

  if (x->move_mode)
    {
      if (rename (src_path, dst_path) == 0)
	{
	  if (x->verbose && S_ISDIR (src_type))
	    printf ("%s -> %s\n", quote_n (0, src_path), quote_n (1, dst_path));
	  if (rename_succeeded)
	    *rename_succeeded = 1;

	  if (command_line_arg)
	    {
	      /* Record destination dev/ino/filename, so that if we are asked
		 to overwrite that file again, we can detect it and fail.  */
	      /* It's fine to use the _source_ stat buffer (src_sb) to get the
	         _destination_ dev/ino, since the rename above can't have
		 changed those, and `mv' always uses lstat.
		 We could limit it further by operating
		 only on non-directories.  */
	      record_file (x->dest_info, dst_path, &src_sb);
	    }

	  return 0;
	}

      /* FIXME: someday, consider what to do when moving a directory into
	 itself but when source and destination are on different devices.  */

      /* This happens when attempting to rename a directory to a
	 subdirectory of itself.  */
      if (errno == EINVAL

	  /* When src_path is on an NFS file system, some types of
	     clients, e.g., SunOS4.1.4 and IRIX-5.3, set errno to EIO
	     instead.  Testing for this here risks misinterpreting a real
	     I/O error as an attempt to move a directory into itself, so
	     FIXME: consider not doing this.  */
	  || errno == EIO

	  /* And with SunOS-4.1.4 client and OpenBSD-2.3 server,
	     we get ENOTEMPTY.  */
	  || errno == ENOTEMPTY)
	{
	  /* FIXME: this is a little fragile in that it relies on rename(2)
	     failing with a specific errno value.  Expect problems on
	     non-POSIX systems.  */
	  error (0, 0, _("cannot move %s to a subdirectory of itself, %s"),
		 quote_n (0, top_level_src_path),
		 quote_n (1, top_level_dst_path));

	  /* Note that there is no need to call forget_created here,
	     (compare with the other calls in this file) since the
	     destination directory didn't exist before.  */

	  *copy_into_self = 1;
	  /* FIXME-cleanup: Don't return zero here; adjust mv.c accordingly.
	     The only caller that uses this code (mv.c) ends up setting its
	     exit status to nonzero when copy_into_self is nonzero.  */
	  return 0;
	}

      /* WARNING: there probably exist systems for which an inter-device
	 rename fails with a value of errno not handled here.
	 If/as those are reported, add them to the condition below.
	 If this happens to you, please do the following and send the output
	 to the bug-reporting address (e.g., in the output of cp --help):
	   touch k; perl -e 'rename "k","/tmp/k" or print "$!(",$!+0,")\n"'
	 where your current directory is on one partion and /tmp is the other.
	 Also, please try to find the E* errno macro name corresponding to
	 the diagnostic and parenthesized integer, and include that in your
	 e-mail.  One way to do that is to run a command like this
	   find /usr/include/. -type f \
	     | xargs grep 'define.*\<E[A-Z]*\>.*\<18\>' /dev/null
	 where you'd replace `18' with the integer in parentheses that
	 was output from the perl one-liner above.
	 If necessary, of course, change `/tmp' to some other directory.  */
      if (errno != EXDEV)
	{
	  /* There are many ways this can happen due to a race condition.
	     When something happens between the initial xstat and the
	     subsequent rename, we can get many different types of errors.
	     For example, if the destination is initially a non-directory
	     or non-existent, but it is created as a directory, the rename
	     fails.  If two `mv' commands try to rename the same file at
	     about the same time, one will succeed and the other will fail.
	     If the permissions on the directory containing the source or
	     destination file are made too restrictive, the rename will
	     fail.  Etc.  */
	  error (0, errno,
		 _("cannot move %s to %s"),
		 quote_n (0, src_path), quote_n (1, dst_path));
	  forget_created (src_sb.st_ino, src_sb.st_dev);
	  return 1;
	}

      /* The rename attempt has failed.  Remove any existing destination
	 file so that a cross-device `mv' acts as if it were really using
	 the rename syscall.  */
      if (unlink (dst_path) && errno != ENOENT)
	{
	  error (0, errno,
	     _("inter-device move failed: %s to %s; unable to remove target"),
		 quote_n (0, src_path), quote_n (1, dst_path));
	  forget_created (src_sb.st_ino, src_sb.st_dev);
	  return 1;
	}

      new_dst = 1;
    }

  delayed_fail = 0;

  /* In certain modes (cp's --symbolic-link), and for certain file types
     (symlinks and hard links) it doesn't make sense to preserve metadata,
     or it's possible to preserve only some of it.
     In such cases, set this variable to zero.  */
  preserve_metadata = 1;

  if (S_ISDIR (src_type))
    {
      struct dir_list *dir;

      /* If this directory has been copied before during the
         recursion, there is a symbolic link to an ancestor
         directory of the symbolic link.  It is impossible to
         continue to copy this, unless we've got an infinite disk.  */

      if (is_ancestor (&src_sb, ancestors))
	{
	  error (0, 0, _("cannot copy cyclic symbolic link %s"),
		 quote (src_path));
	  goto un_backup;
	}

      /* Insert the current directory in the list of parents.  */

      dir = (struct dir_list *) alloca (sizeof (struct dir_list));
      dir->parent = ancestors;
      dir->ino = src_sb.st_ino;
      dir->dev = src_sb.st_dev;

      if (new_dst || !S_ISDIR (dst_sb.st_mode))
	{
	  /* Create the new directory writable and searchable, so
             we can create new entries in it.  */

	  if (mkdir (dst_path, (src_mode & x->umask_kill) | S_IRWXU))
	    {
	      error (0, errno, _("cannot create directory %s"),
		     quote (dst_path));
	      goto un_backup;
	    }

	  /* Insert the created directory's inode and device
             numbers into the search structure, so that we can
             avoid copying it again.  */

	  if (remember_created (dst_path))
	    goto un_backup;

	  if (x->verbose)
	    printf ("%s -> %s\n", quote_n (0, src_path), quote_n (1, dst_path));
	}

      /* Are we crossing a file system boundary?  */
      if (x->one_file_system && device != 0 && device != src_sb.st_dev)
	return 0;

      /* Copy the contents of the directory.  */

      if (copy_dir (src_path, dst_path, new_dst, &src_sb, dir, x,
		    copy_into_self))
	{
	  /* Don't just return here -- otherwise, the failure to read a
	     single file in a source directory would cause the containing
	     destination directory not to have owner/perms set properly.  */
	  delayed_fail = 1;
	}
    }
#ifdef S_ISLNK
  else if (x->symbolic_link)
    {
      preserve_metadata = 0;

      if (*src_path != '/')
	{
	  /* Check that DST_PATH denotes a file in the current directory.  */
	  struct stat dot_sb;
	  struct stat dst_parent_sb;
	  char *dst_parent;
	  int in_current_dir;

	  dst_parent = dir_name (dst_path);

	  in_current_dir = (STREQ (".", dst_parent)
			    /* If either stat call fails, it's ok not to report
			       the failure and say dst_path is in the current
			       directory.  Other things will fail later.  */
			    || stat (".", &dot_sb)
			    || stat (dst_parent, &dst_parent_sb)
			    || SAME_INODE (dot_sb, dst_parent_sb));
	  free (dst_parent);

	  if (! in_current_dir)
	    {
	      error (0, 0,
	   _("%s: can make relative symbolic links only in current directory"),
		     quote (dst_path));
	      goto un_backup;
	    }
	}
      if (symlink (src_path, dst_path))
	{
	  error (0, errno, _("cannot create symbolic link %s to %s"),
		 quote_n (0, dst_path), quote_n (1, src_path));
	  goto un_backup;
	}
    }
#endif
  else if (x->hard_link)
    {
      preserve_metadata = 0;
      if (link (src_path, dst_path))
	{
	  error (0, errno, _("cannot create link %s"), quote (dst_path));
	  goto un_backup;
	}
    }
  else if (S_ISREG (src_type)
	   || (x->copy_as_regular && !S_ISDIR (src_type)
#ifdef S_ISLNK
	       && !S_ISLNK (src_type)
#endif
	       ))
    {
      copied_as_regular = 1;
      /* POSIX says the permission bits of the source file must be
	 used as the 3rd argument in the open call, but that's not consistent
	 with historical practice.  */
      if (copy_reg (src_path, dst_path, x,
		    get_dest_mode (x, src_mode), &new_dst, &src_sb))
	goto un_backup;
    }
  else
#ifdef S_ISFIFO
  if (S_ISFIFO (src_type))
    {
      if (mkfifo (dst_path, get_dest_mode (x, src_mode)))
	{
	  error (0, errno, _("cannot create fifo %s"), quote (dst_path));
	  goto un_backup;
	}
    }
  else
#endif
    if (S_ISBLK (src_type) || S_ISCHR (src_type)
#ifdef S_ISSOCK
	|| S_ISSOCK (src_type)
#endif
	)
    {
      if (mknod (dst_path, get_dest_mode (x, src_mode), src_sb.st_rdev))
	{
	  error (0, errno, _("cannot create special file %s"),
		 quote (dst_path));
	  goto un_backup;
	}
    }
  else
#ifdef S_ISLNK
  if (S_ISLNK (src_type))
    {
      char *src_link_val = xreadlink (src_path);
      if (src_link_val == NULL)
	{
	  error (0, errno, _("cannot read symbolic link %s"), quote (src_path));
	  goto un_backup;
	}

      if (!symlink (src_link_val, dst_path))
	free (src_link_val);
      else
	{
	  int saved_errno = errno;
	  int same_link = 0;
	  if (x->update && !new_dst && S_ISLNK (dst_sb.st_mode))
	    {
	      /* See if the destination is already the desired symlink.  */
	      size_t src_link_len = strlen (src_link_val);
	      char *dest_link_val = (char *) alloca (src_link_len + 1);
	      int dest_link_len = readlink (dst_path, dest_link_val,
					    src_link_len + 1);
	      if ((size_t) dest_link_len == src_link_len
		  && strncmp (dest_link_val, src_link_val, src_link_len) == 0)
		same_link = 1;
	    }
	  free (src_link_val);

	  if (! same_link)
	    {
	      error (0, saved_errno, _("cannot create symbolic link %s"),
		     quote (dst_path));
	      goto un_backup;
	    }
	}

      /* There's no need to preserve timestamps or permissions.  */
      preserve_metadata = 0;

      if (x->preserve_ownership)
	{
	  /* Preserve the owner and group of the just-`copied'
	     symbolic link, if possible.  */
# if HAVE_LCHOWN
	  if (DO_CHOWN (lchown, dst_path, src_sb.st_uid, src_sb.st_gid))
	    {
	      error (0, errno, _("failed to preserve ownership for %s"),
		     dst_path);
	      goto un_backup;
	    }
# else
	  /* Can't preserve ownership of symlinks.
	     FIXME: maybe give a warning or even error for symlinks
	     in directories with the sticky bit set -- there, not
	     preserving owner/group is a potential security problem.  */
# endif
	}
    }
  else
#endif
    {
      error (0, 0, _("%s has unknown file type"), quote (src_path));
      goto un_backup;
    }

  if (command_line_arg)
    record_file (x->dest_info, dst_path, NULL);

  if ( ! preserve_metadata)
    return 0;

  /* POSIX says that `cp -p' must restore the following:
     - permission bits
     - setuid, setgid bits
     - owner and group
     If it fails to restore any of those, we may give a warning but
     the destination must not be removed.
     FIXME: implement the above. */

  /* Adjust the times (and if possible, ownership) for the copy.
     chown turns off set[ug]id bits for non-root,
     so do the chmod last.  */

  if (x->preserve_timestamps)
    {
      struct utimbuf utb;

      /* There's currently no interface to set file timestamps with
	 better than 1-second resolution, so discard any fractional
	 part of the source timestamp.  */

      utb.actime = src_sb.st_atime;
      utb.modtime = src_sb.st_mtime;

      if (utime (dst_path, &utb))
	{
	  error (0, errno, _("preserving times for %s"), quote (dst_path));
	  if (x->require_preserve)
	    return 1;
	}
    }

  /* Avoid calling chown if we know it's not necessary.  */
  if (x->preserve_ownership
      && (new_dst || !SAME_OWNER_AND_GROUP (src_sb, dst_sb)))
    {
      ran_chown = 1;
      if (DO_CHOWN (chown, dst_path, src_sb.st_uid, src_sb.st_gid))
	{
	  error (0, errno, _("failed to preserve ownership for %s"),
		 quote (dst_path));
	  if (x->require_preserve)
	    return 1;
	}
    }

#if HAVE_STRUCT_STAT_ST_AUTHOR
  /* Preserve the st_author field.  */
  {
    file_t file = file_name_lookup (dst_path, 0, 0);
    if (file_chauthor (file, src_sb.st_author))
      error (0, errno, _("failed to preserve authorship for %s"),
	     quote (dst_path));
    mach_port_deallocate (mach_task_self (), file);
  }
#endif

  /* Permissions of newly-created regular files were set upon `open' in
     copy_reg.  But don't return early if there were any special bits and
     we had to run chown, because the chown must have reset those bits.  */
  if ((new_dst && copied_as_regular)
      && !(ran_chown && (src_mode & ~S_IRWXUGO)))
    return delayed_fail;

  if ((x->preserve_mode || new_dst)
      && (x->copy_as_regular || S_ISREG (src_type) || S_ISDIR (src_type)))
    {
      if (chmod (dst_path, get_dest_mode (x, src_mode)))
	{
	  error (0, errno, _("setting permissions for %s"), quote (dst_path));
	  if (x->set_mode || x->require_preserve)
	    return 1;
	}
    }

  return delayed_fail;

un_backup:

  /* We have failed to create the destination file.
     If we've just added a dev/ino entry via the remember_copied
     call above (i.e., unless we've just failed to create a hard link),
     remove the entry associating the source dev/ino with the
     destination file name, so we don't try to `preserve' a link
     to a file we didn't create.  */
  if (earlier_file == NULL)
    forget_created (src_sb.st_ino, src_sb.st_dev);

  if (dst_backup)
    {
      if (rename (dst_backup, dst_path))
	error (0, errno, _("cannot un-backup %s"), quote (dst_path));
      else
	{
	  if (x->verbose)
	    printf (_("%s -> %s (unbackup)\n"),
		    quote_n (0, dst_backup), quote_n (1, dst_path));
	}
    }
  return 1;
}