backup_file.c revision 9d7d4458d94d0aac0a7edf999368eb18f89cb76a
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/*
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen SSSD
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen Backup files
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen Copyright (C) Simo Sorce 2009
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen This program is free software; you can redistribute it and/or modify
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen it under the terms of the GNU General Public License as published by
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen the Free Software Foundation; either version 3 of the License, or
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen (at your option) any later version.
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen This program is distributed in the hope that it will be useful,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen but WITHOUT ANY WARRANTY; without even the implied warranty of
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen GNU General Public License for more details.
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen You should have received a copy of the GNU General Public License
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen along with this program. If not, see <http://www.gnu.org/licenses/>.
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen*/
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#include "util/util.h"
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#include <fcntl.h>
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#include <stddef.h>
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#include <stdlib.h>
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen#define BUFFER_SIZE 65536
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainenint backup_file(const char *src_file, int dbglvl)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen TALLOC_CTX *tmp_ctx = NULL;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen char buf[BUFFER_SIZE];
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen int src_fd = -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen int dst_fd = -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen char *dst_file;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ssize_t numread;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ssize_t written;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen int ret, i;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen src_fd = open(src_file, O_RDONLY);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (src_fd < 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = errno;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(dbglvl, ("Error (%d [%s]) opening source file %s\n",
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret, strerror(ret), src_file));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen goto done;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen }
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainen tmp_ctx = talloc_new(NULL);
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainen if (!tmp_ctx) {
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen ret = ENOMEM;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen goto done;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen }
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainen /* try a few times to come up with a new backup file, then give up */
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainen for (i = 0; i < 10; i++) {
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainen if (i == 0) {
d4847b921058734e0668bc7690465c91523d9ec0Martti Rannanjärvi dst_file = talloc_asprintf(tmp_ctx, "%s.bak", src_file);
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainen } else {
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainen dst_file = talloc_asprintf(tmp_ctx, "%s.bak%d", src_file, i);
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen }
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen if (!dst_file) {
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen ret = ENOMEM;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen goto done;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen errno = 0;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen dst_fd = open(dst_file, O_CREAT|O_EXCL|O_WRONLY, 0600);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = errno;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
f3391d65cc830eab22ca6c5941774de682716edbTimo Sirainen if (dst_fd >= 0) break;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
f3391d65cc830eab22ca6c5941774de682716edbTimo Sirainen if (ret != EEXIST) {
8528048c7b82c745bcfa5a6b1394251b3aaeb129Josef 'Jeff' Sipek DEBUG(dbglvl, ("Error (%d [%s]) opening destination file %s\n",
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret, strerror(ret), dst_file));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen goto done;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen }
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen }
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (ret != 0) {
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen DEBUG(dbglvl, ("Error (%d [%s]) opening destination file %s\n",
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen ret, strerror(ret), dst_file));
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen goto done;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen }
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen /* copy file contents */
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen while (1) {
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen errno = 0;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen numread = sss_atomic_read_s(src_fd, buf, BUFFER_SIZE);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (numread < 0) {
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen ret = errno;
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen DEBUG(dbglvl, ("Error (%d [%s]) reading from source %s\n",
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen ret, strerror(ret), src_file));
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen goto done;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen }
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (numread == 0) break;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen errno = 0;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen written = sss_atomic_write_s(dst_fd, buf, numread);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (written == -1) {
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen ret = errno;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen DEBUG(dbglvl, ("Error (%d [%s]) writing to destination %s\n",
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen ret, strerror(ret), dst_file));
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen goto done;
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen }
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen if (written != numread) {
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen DEBUG(dbglvl, ("Wrote %d bytes expected %d bytes\n",
7da0a157dbcb64d3e97c01bcc87262bd944c6890Timo Sirainen written, numread));
7da0a157dbcb64d3e97c01bcc87262bd944c6890Timo Sirainen ret = EIO;
7da0a157dbcb64d3e97c01bcc87262bd944c6890Timo Sirainen goto done;
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen }
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = EOK;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainendone:
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (src_fd != -1) close(src_fd);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (dst_fd != -1) close(dst_fd);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen talloc_free(tmp_ctx);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return ret;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen