summaryrefslogtreecommitdiff
path: root/src/copy.h
blob: 8e0b4080e341141f57bad900cdf765bc2d5047f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/* core functions for copying files and directories
   Copyright (C) 89, 90, 91, 1995-2009 Free Software Foundation, Inc.

   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 3 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, see <http://www.gnu.org/licenses/>.  */

/* Extracted from cp.c and librarified by Jim Meyering.  */

#ifndef COPY_H
# define COPY_H

# include <stdbool.h>
# include "hash.h"

/* Control creation of sparse files (files with holes).  */
enum Sparse_type
{
  SPARSE_UNUSED,

  /* Never create holes in DEST.  */
  SPARSE_NEVER,

  /* This is the default.  Use a crude (and sometimes inaccurate)
     heuristic to determine if SOURCE has holes.  If so, try to create
     holes in DEST.  */
  SPARSE_AUTO,

  /* For every sufficiently long sequence of bytes in SOURCE, try to
     create a corresponding hole in DEST.  There is a performance penalty
     here because CP has to search for holes in SRC.  But if the holes are
     big enough, that penalty can be offset by the decrease in the amount
     of data written to disk.   */
  SPARSE_ALWAYS
};

/* This type is used to help mv (via copy.c) distinguish these cases.  */
enum Interactive
{
  I_ALWAYS_YES = 1,
  I_ALWAYS_NO,
  I_ASK_USER,
  I_UNSPECIFIED
};

/* How to handle symbolic links.  */
enum Dereference_symlink
{
  DEREF_UNDEFINED = 1,

  /* Copy the symbolic link itself.  -P  */
  DEREF_NEVER,

  /* If the symbolic is a command line argument, then copy
     its referent.  Otherwise, copy the symbolic link itself.  -H  */
  DEREF_COMMAND_LINE_ARGUMENTS,

  /* Copy the referent of the symbolic link.  -L  */
  DEREF_ALWAYS
};

# define VALID_SPARSE_MODE(Mode)	\
  ((Mode) == SPARSE_NEVER		\
   || (Mode) == SPARSE_AUTO		\
   || (Mode) == SPARSE_ALWAYS)

/* These options control how files are copied by at least the
   following programs: mv (when rename doesn't work), cp, install.
   So, if you add a new member, be sure to initialize it in
   mv.c, cp.c, and install.c.  */
struct cp_options
{
  enum backup_type backup_type;

  /* How to handle symlinks in the source.  */
  enum Dereference_symlink dereference;

  /* This value is used to determine whether to prompt before removing
     each existing destination file.  It works differently depending on
     whether move_mode is set.  See code/comments in copy.c.  */
  enum Interactive interactive;

  /* Control creation of sparse files.  */
  enum Sparse_type sparse_mode;

  /* Set the mode of the destination file to exactly this value
     if SET_MODE is nonzero.  */
  mode_t mode;

  /* If true, copy all files except (directories and, if not dereferencing
     them, symbolic links,) as if they were regular files.  */
  bool copy_as_regular;

  /* If true, remove each existing destination nondirectory before
     trying to open it.  */
  bool unlink_dest_before_opening;

  /* If true, first try to open each existing destination nondirectory,
     then, if the open fails, unlink and try again.
     This option must be set for `cp -f', in case the destination file
     exists when the open is attempted.  It is irrelevant to `mv' since
     any destination is sure to be removed before the open.  */
  bool unlink_dest_after_failed_open;

  /* If true, create hard links instead of copying files.
     Create destination directories as usual. */
  bool hard_link;

  /* If true, rather than copying, first attempt to use rename.
     If that fails, then resort to copying.  */
  bool move_mode;

  /* Whether this process has appropriate privileges to chown a file
     whose owner is not the effective user ID.  */
  bool chown_privileges;

  /* Whether this process has appropriate privileges to do the
     following operations on a file even when it is owned by some
     other user: set the file's atime, mtime, mode, or ACL; remove or
     rename an entry in the file even though it is a sticky directory,
     or to mount on the file.  */
  bool owner_privileges;

  /* If true, when copying recursively, skip any subdirectories that are
     on different file systems from the one we started on.  */
  bool one_file_system;

  /* If true, attempt to give the copies the original files' permissions,
     owner, group, and timestamps. */
  bool preserve_ownership;
  bool preserve_mode;
  bool preserve_timestamps;

  /* Enabled for mv, and for cp by the --preserve=links option.
     If true, attempt to preserve in the destination files any
     logical hard links between the source files.  If used with cp's
     --no-dereference option, and copying two hard-linked files,
     the two corresponding destination files will also be hard linked.

     If used with cp's --dereference (-L) option, then, as that option implies,
     hard links are *not* preserved.  However, when copying a file F and
     a symlink S to F, the resulting S and F in the destination directory
     will be hard links to the same file (a copy of F).  */
  bool preserve_links;

  /* If true and any of the above (for preserve) file attributes cannot
     be applied to a destination file, treat it as a failure and return
     nonzero immediately.  E.g. for cp -p this must be true, for mv it
     must be false.  */
  bool require_preserve;

  /* If true, attempt to preserve the SELinux security context, too.
     Set this only if the kernel is SELinux enabled.  */
  bool preserve_security_context;

  /* Useful only when preserve_security_context is true.
     If true, a failed attempt to preserve a file's security context
     propagates failure "out" to the caller.  If false, a failure to
     preserve a file's security context does not change the invoking
     application's exit status.  Give diagnostics for failed syscalls
     regardless of this setting.  For example, with "cp --preserve=context"
     this flag is "true", while with "cp -a", it is false.  That means
     "cp -a" attempts to preserve any security context, but does not
     fail if it is unable to do so.  */
  bool require_preserve_context;

  /* If true, attempt to preserve extended attributes using libattr.
     Ignored if coreutils are compiled without xattr support. */
  bool preserve_xattr;

  /* Useful only when preserve_xattr is true.
     If true, a failed attempt to preserve file's extended attributes
     propagates failure "out" to the caller.  If false, a failure to
     preserve file's extended attributes does not change the invoking
     application's exit status.  Give diagnostics for failed syscalls
     regardless of this setting.  For example, with "cp --preserve=xattr"
     this flag is "true", while with "cp --preserve=all", it is false. */
  bool require_preserve_xattr;

  /* Used as difference boolean between cp -a and cp -dR --preserve=all.
     If true, non-mandatory failure diagnostics are not displayed. This
     should prevent poluting cp -a output.
   */
  bool reduce_diagnostics;

  /* If true, copy directories recursively and copy special files
     as themselves rather than copying their contents. */
  bool recursive;

  /* If true, set file mode to value of MODE.  Otherwise,
     set it based on current umask modified by UMASK_KILL.  */
  bool set_mode;

  /* If true, create symbolic links instead of copying files.
     Create destination directories as usual. */
  bool symbolic_link;

  /* If true, do not copy a nondirectory that has an existing destination
     with the same or newer modification time. */
  bool update;

  /* If true, display the names of the files before copying them. */
  bool verbose;

  /* If true, stdin is a tty.  */
  bool stdin_tty;

  /* If true, open a dangling destination symlink when not in move_mode.
     Otherwise, copy_reg gives a diagnostic (it refuses to write through
     such a symlink) and returns false.  */
  bool open_dangling_dest_symlink;

  /* This is a set of destination name/inode/dev triples.  Each such triple
     represents a file we have created corresponding to a source file name
     that was specified on the command line.  Use it to avoid clobbering
     source files in commands like this:
       rm -rf a b c; mkdir a b c; touch a/f b/f; mv a/f b/f c
     For now, it protects only regular files when copying (i.e. not renaming).
     When renaming, it protects all non-directories.
     Use dest_info_init to initialize it, or set it to NULL to disable
     this feature.  */
  Hash_table *dest_info;

  /* FIXME */
  Hash_table *src_info;
};

# define XSTAT(X, Src_name, Src_sb) \
  ((X)->dereference == DEREF_NEVER \
   ? lstat (Src_name, Src_sb) \
   : stat (Src_name, Src_sb))

/* Arrange to make rename calls go through the wrapper function
   on systems with a rename function that fails for a source file name
   specified with a trailing slash.  */
# if RENAME_TRAILING_SLASH_BUG
int rpl_rename (const char *, const char *);
#  undef rename
#  define rename rpl_rename
# endif

bool copy (char const *src_name, char const *dst_name,
	   bool nonexistent_dst, const struct cp_options *options,
	   bool *copy_into_self, bool *rename_succeeded);

void dest_info_init (struct cp_options *);
void src_info_init (struct cp_options *);

void cp_options_default (struct cp_options *);
bool chown_failure_ok (struct cp_options const *);
mode_t cached_umask (void);

#endif