| | 93 | int |
|---|
| | 94 | noit_xmlSaveToFile(xmlDocPtr doc, const char *filename) { |
|---|
| | 95 | int rv = -1, fd, have_backup = 0, once; |
|---|
| | 96 | char tmpfile[PATH_MAX], bakfile[PATH_MAX]; |
|---|
| | 97 | xmlOutputBufferPtr out; |
|---|
| | 98 | xmlCharEncodingHandlerPtr enc; |
|---|
| | 99 | |
|---|
| | 100 | snprintf(tmpfile, sizeof(tmpfile), "%s.tmp", filename); |
|---|
| | 101 | snprintf(bakfile, sizeof(bakfile), "%s.bak", filename); |
|---|
| | 102 | once = 1; |
|---|
| | 103 | mkbkup: |
|---|
| | 104 | if(link(filename, bakfile) == 0) { |
|---|
| | 105 | unlink(filename); |
|---|
| | 106 | have_backup = 1; |
|---|
| | 107 | } |
|---|
| | 108 | else if (errno != ENOENT) { |
|---|
| | 109 | if(!once) return -1; |
|---|
| | 110 | once = 0; |
|---|
| | 111 | if(errno == EEXIST) { |
|---|
| | 112 | unlink(bakfile); |
|---|
| | 113 | goto mkbkup; |
|---|
| | 114 | } |
|---|
| | 115 | noitL(noit_error, "Cannot create backup for %s: %s\n", |
|---|
| | 116 | filename, strerror(errno)); |
|---|
| | 117 | return -1; |
|---|
| | 118 | } |
|---|
| | 119 | else { |
|---|
| | 120 | noitL(noit_debug, "link(%s,%s) -> %s\n", filename, bakfile, strerror(errno)); |
|---|
| | 121 | } |
|---|
| | 122 | |
|---|
| | 123 | retry: |
|---|
| | 124 | fd = open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0640); |
|---|
| | 125 | if(fd < 0) { |
|---|
| | 126 | if(!once) return -1; |
|---|
| | 127 | once = 0; |
|---|
| | 128 | if(errno == ENOENT) { |
|---|
| | 129 | if(mkdir_for_file(tmpfile, 0750) == 0) goto retry; |
|---|
| | 130 | } |
|---|
| | 131 | if(errno == EEXIST) { |
|---|
| | 132 | unlink(tmpfile); |
|---|
| | 133 | goto retry; |
|---|
| | 134 | } |
|---|
| | 135 | return -1; |
|---|
| | 136 | } |
|---|
| | 137 | enc = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8); |
|---|
| | 138 | out = xmlOutputBufferCreateFd(fd, enc); |
|---|
| | 139 | assert(out); |
|---|
| | 140 | xmlSaveFormatFileTo(out, doc, "utf8", 1); |
|---|
| | 141 | close(fd); |
|---|
| | 142 | rv = 0; |
|---|
| | 143 | if(link(tmpfile, filename)) { |
|---|
| | 144 | rv = -1; |
|---|
| | 145 | if(link(bakfile, filename) != 0) have_backup = 0; |
|---|
| | 146 | } |
|---|
| | 147 | unlink(tmpfile); |
|---|
| | 148 | if(have_backup) |
|---|
| | 149 | unlink(bakfile); |
|---|
| | 150 | return rv; |
|---|
| | 151 | } |
|---|