version 1.1.1.3, 2016/11/01 09:54:32
|
version 1.1.1.4, 2021/03/17 00:32:36
|
Line 2
|
Line 2
|
* Backup handling code. |
* Backup handling code. |
* |
* |
* Copyright (C) 1999 Andrew Tridgell |
* Copyright (C) 1999 Andrew Tridgell |
* Copyright (C) 2003-2015 Wayne Davison | * Copyright (C) 2003-2020 Wayne Davison |
* |
* |
* This program is free software; you can redistribute it and/or modify |
* 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 |
* it under the terms of the GNU General Public License as published by |
Line 29 extern int preserve_specials;
|
Line 29 extern int preserve_specials;
|
extern int preserve_links; |
extern int preserve_links; |
extern int safe_symlinks; |
extern int safe_symlinks; |
extern int backup_dir_len; |
extern int backup_dir_len; |
|
extern int backup_dir_dels_len; |
extern unsigned int backup_dir_remainder; |
extern unsigned int backup_dir_remainder; |
|
extern unsigned int backup_dir_dels_remainder; |
extern char backup_dir_buf[MAXPATHLEN]; |
extern char backup_dir_buf[MAXPATHLEN]; |
|
extern char backup_dir_dels_buf[MAXPATHLEN]; |
extern char *backup_suffix; |
extern char *backup_suffix; |
|
extern char *backup_suffix_dels; |
extern char *backup_dir; |
extern char *backup_dir; |
|
extern char *backup_dir_dels; |
|
|
|
static BOOL deleting; |
|
|
/* Returns -1 on error, 0 on missing dir, and 1 on present dir. */ |
/* Returns -1 on error, 0 on missing dir, and 1 on present dir. */ |
static int validate_backup_dir(void) | static int validate_backup_dir(char *buf) |
{ |
{ |
STRUCT_STAT st; |
STRUCT_STAT st; |
|
|
if (do_lstat(backup_dir_buf, &st) < 0) { | if (do_lstat(buf, &st) < 0) { |
if (errno == ENOENT) |
if (errno == ENOENT) |
return 0; |
return 0; |
rsyserr(FERROR, errno, "backup lstat %s failed", backup_dir_buf); | rsyserr(FERROR, errno, "backup lstat %s failed", buf); |
return -1; |
return -1; |
} |
} |
if (!S_ISDIR(st.st_mode)) { |
if (!S_ISDIR(st.st_mode)) { |
int flags = get_del_for_flag(st.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE; |
int flags = get_del_for_flag(st.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE; |
if (delete_item(backup_dir_buf, st.st_mode, flags) == 0) | if (delete_item(buf, st.st_mode, flags) == 0) |
return 0; |
return 0; |
return -1; |
return -1; |
} |
} |
Line 58 static int validate_backup_dir(void)
|
Line 65 static int validate_backup_dir(void)
|
* backup_dir_buf. Any new directories (compared to the prior backup |
* backup_dir_buf. Any new directories (compared to the prior backup |
* path) are ensured to exist as directories, replacing anything else |
* path) are ensured to exist as directories, replacing anything else |
* that may be in the way (e.g. a symlink). */ |
* that may be in the way (e.g. a symlink). */ |
static BOOL copy_valid_path(const char *fname) | static BOOL copy_valid_path(const char *fname, char *buf, int prefix_len, unsigned int remainder, const char *suffix) |
{ |
{ |
const char *f; |
const char *f; |
int val; |
int val; |
BOOL ret = True; |
BOOL ret = True; |
stat_x sx; |
stat_x sx; |
char *b, *rel = backup_dir_buf + backup_dir_len, *name = rel; | char *b, *rel = buf + prefix_len, *name = rel; |
|
|
for (f = fname, b = rel; *f && *f == *b; f++, b++) { |
for (f = fname, b = rel; *f && *f == *b; f++, b++) { |
if (*b == '/') |
if (*b == '/') |
name = b + 1; |
name = b + 1; |
} |
} |
|
|
if (stringjoin(rel, backup_dir_remainder, fname, backup_suffix, NULL) >= backup_dir_remainder) { | if (stringjoin(rel, remainder, fname, suffix, NULL) >= remainder) { |
rprintf(FERROR, "backup filename too long\n"); |
rprintf(FERROR, "backup filename too long\n"); |
*name = '\0'; |
*name = '\0'; |
return False; |
return False; |
Line 82 static BOOL copy_valid_path(const char *fname)
|
Line 89 static BOOL copy_valid_path(const char *fname)
|
return True; |
return True; |
*b = '\0'; |
*b = '\0'; |
|
|
val = validate_backup_dir(); | val = validate_backup_dir(buf); |
if (val == 0) |
if (val == 0) |
break; |
break; |
if (val < 0) { |
if (val < 0) { |
Line 98 static BOOL copy_valid_path(const char *fname)
|
Line 105 static BOOL copy_valid_path(const char *fname)
|
for ( ; b; name = b + 1, b = strchr(name, '/')) { |
for ( ; b; name = b + 1, b = strchr(name, '/')) { |
*b = '\0'; |
*b = '\0'; |
|
|
while (do_mkdir(backup_dir_buf, ACCESSPERMS) < 0) { | while (do_mkdir(buf, ACCESSPERMS) < 0) { |
if (errno == EEXIST) { |
if (errno == EEXIST) { |
val = validate_backup_dir(); | val = validate_backup_dir(buf); |
if (val > 0) |
if (val > 0) |
break; |
break; |
if (val == 0) |
if (val == 0) |
Line 134 static BOOL copy_valid_path(const char *fname)
|
Line 141 static BOOL copy_valid_path(const char *fname)
|
free_xattr(&sx); |
free_xattr(&sx); |
} |
} |
#endif |
#endif |
set_file_attrs(backup_dir_buf, file, NULL, NULL, 0); | set_file_attrs(buf, file, NULL, NULL, 0); |
unmake_file(file); |
unmake_file(file); |
} |
} |
|
|
Line 156 static BOOL copy_valid_path(const char *fname)
|
Line 163 static BOOL copy_valid_path(const char *fname)
|
/* Make a complete pathname for backup file and verify any new path elements. */ |
/* Make a complete pathname for backup file and verify any new path elements. */ |
char *get_backup_name(const char *fname) |
char *get_backup_name(const char *fname) |
{ |
{ |
|
char *buf = deleting ? backup_dir_dels_buf : backup_dir_buf; |
|
char *suffix = deleting ? backup_suffix_dels : backup_suffix; |
|
|
if (backup_dir) { |
if (backup_dir) { |
|
int prefix_len = deleting ? backup_dir_dels_len : backup_dir_len; |
|
unsigned int remainder = deleting ? backup_dir_dels_remainder : backup_dir_remainder; |
static int initialized = 0; |
static int initialized = 0; |
if (!initialized) { |
if (!initialized) { |
int ret; |
int ret; |
if (backup_dir_len > 1) |
if (backup_dir_len > 1) |
backup_dir_buf[backup_dir_len-1] = '\0'; |
backup_dir_buf[backup_dir_len-1] = '\0'; |
ret = make_path(backup_dir_buf, 0); | ret = make_path(backup_dir_buf, ACCESSPERMS, 0); |
if (backup_dir_len > 1) |
if (backup_dir_len > 1) |
backup_dir_buf[backup_dir_len-1] = '/'; |
backup_dir_buf[backup_dir_len-1] = '/'; |
if (ret < 0) |
if (ret < 0) |
Line 170 char *get_backup_name(const char *fname)
|
Line 182 char *get_backup_name(const char *fname)
|
initialized = 1; |
initialized = 1; |
} |
} |
/* copy fname into backup_dir_buf while validating the dirs. */ |
/* copy fname into backup_dir_buf while validating the dirs. */ |
if (copy_valid_path(fname)) | if (copy_valid_path(fname, buf, prefix_len, remainder, suffix)) |
return backup_dir_buf; | return buf; |
/* copy_valid_path() has printed an error message. */ |
/* copy_valid_path() has printed an error message. */ |
return NULL; |
return NULL; |
} |
} |
|
|
if (stringjoin(backup_dir_buf, MAXPATHLEN, fname, backup_suffix, NULL) < MAXPATHLEN) | if (stringjoin(backup_dir_buf, MAXPATHLEN, fname, suffix, NULL) < MAXPATHLEN) |
return backup_dir_buf; | return buf; |
|
|
rprintf(FERROR, "backup filename too long\n"); |
rprintf(FERROR, "backup filename too long\n"); |
return NULL; |
return NULL; |
Line 336 int make_backup(const char *fname, BOOL prefer_rename)
|
Line 348 int make_backup(const char *fname, BOOL prefer_rename)
|
|
|
save_preserve_xattrs = preserve_xattrs; |
save_preserve_xattrs = preserve_xattrs; |
preserve_xattrs = 0; |
preserve_xattrs = 0; |
set_file_attrs(buf, file, NULL, fname, 0); | set_file_attrs(buf, file, NULL, fname, ATTRS_ACCURATE_TIME); |
preserve_xattrs = save_preserve_xattrs; |
preserve_xattrs = save_preserve_xattrs; |
|
|
unmake_file(file); |
unmake_file(file); |
Line 350 int make_backup(const char *fname, BOOL prefer_rename)
|
Line 362 int make_backup(const char *fname, BOOL prefer_rename)
|
success: |
success: |
if (INFO_GTE(BACKUP, 1)) |
if (INFO_GTE(BACKUP, 1)) |
rprintf(FINFO, "backed up %s to %s\n", fname, buf); |
rprintf(FINFO, "backed up %s to %s\n", fname, buf); |
|
return ret; |
|
} |
|
|
|
/* backup switch routine called only when backing-up removed file */ |
|
int safe_delete(const char *fname) |
|
{ |
|
int ret; |
|
deleting = 1; |
|
ret = make_backup(fname, True); |
|
deleting = 0; |
return ret; |
return ret; |
} |
} |