If we are replacing an existing hard link, symlink, device, or special file, * create a temp-name item and rename it into place. A symlimk specifies slnk, * a hard link specifies hlnk, otherwise we create a device based on rdev. * Specify 0 for the del_for_flag if there is not a file to replace. This * returns 1 on success and 0 on failure. */
| 2003 | * Specify 0 for the del_for_flag if there is not a file to replace. This |
| 2004 | * returns 1 on success and 0 on failure. */ |
| 2005 | int atomic_create(struct file_struct *file, char *fname, const char *slnk, const char *hlnk, |
| 2006 | dev_t rdev, stat_x *sxp, int del_for_flag) |
| 2007 | { |
| 2008 | char tmpname[MAXPATHLEN]; |
| 2009 | const char *create_name; |
| 2010 | int skip_atomic, dir_in_the_way = del_for_flag && S_ISDIR(sxp->st.st_mode); |
| 2011 | |
| 2012 | if (!del_for_flag || dir_in_the_way || tmpdir || !get_tmpname(tmpname, fname, True)) |
| 2013 | skip_atomic = 1; |
| 2014 | else |
| 2015 | skip_atomic = 0; |
| 2016 | |
| 2017 | if (del_for_flag) { |
| 2018 | if (make_backups > 0 && !dir_in_the_way) { |
| 2019 | if (!make_backup(fname, skip_atomic)) |
| 2020 | return 0; |
| 2021 | } else if (skip_atomic) { |
| 2022 | int del_opts = delete_mode || force_delete ? DEL_RECURSE : 0; |
| 2023 | if (delete_item(fname, sxp->st.st_mode, del_opts | del_for_flag) != 0) |
| 2024 | return 0; |
| 2025 | } |
| 2026 | } |
| 2027 | |
| 2028 | create_name = skip_atomic ? fname : tmpname; |
| 2029 | |
| 2030 | if (slnk) { |
| 2031 | #ifdef SUPPORT_LINKS |
| 2032 | if (do_symlink_at(slnk, create_name) < 0) { |
| 2033 | rsyserr(FERROR_XFER, errno, "symlink %s -> \"%s\" failed", |
| 2034 | full_fname(create_name), slnk); |
| 2035 | return 0; |
| 2036 | } |
| 2037 | #else |
| 2038 | return 0; |
| 2039 | #endif |
| 2040 | } else if (hlnk) { |
| 2041 | #ifdef SUPPORT_HARD_LINKS |
| 2042 | if (!hard_link_one(file, create_name, hlnk, 0)) |
| 2043 | return 0; |
| 2044 | #else |
| 2045 | return 0; |
| 2046 | #endif |
| 2047 | } else { |
| 2048 | if (do_mknod_at(create_name, file->mode, rdev) < 0) { |
| 2049 | rsyserr(FERROR_XFER, errno, "mknod %s failed", |
| 2050 | full_fname(create_name)); |
| 2051 | return 0; |
| 2052 | } |
| 2053 | } |
| 2054 | |
| 2055 | if (!skip_atomic) { |
| 2056 | if (do_rename_at(tmpname, fname) < 0) { |
| 2057 | char *full_tmpname = strdup(full_fname(tmpname)); |
| 2058 | if (full_tmpname == NULL) |
| 2059 | out_of_memory("atomic_create"); |
| 2060 | rsyserr(FERROR_XFER, errno, "rename %s -> \"%s\" failed", |
| 2061 | full_tmpname, full_fname(fname)); |
| 2062 | free(full_tmpname); |
no test coverage detected