1*912a040bShaad /* $NetBSD: libdm-file.c,v 1.2 2011/01/05 14:57:28 haad Exp $ */
256a34939Shaad
356a34939Shaad /*
456a34939Shaad * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
556a34939Shaad * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
656a34939Shaad *
756a34939Shaad * This file is part of the device-mapper userspace tools.
856a34939Shaad *
956a34939Shaad * This copyrighted material is made available to anyone wishing to use,
1056a34939Shaad * modify, copy, or redistribute it subject to the terms and conditions
1156a34939Shaad * of the GNU Lesser General Public License v.2.1.
1256a34939Shaad *
1356a34939Shaad * You should have received a copy of the GNU Lesser General Public License
1456a34939Shaad * along with this program; if not, write to the Free Software Foundation,
1556a34939Shaad * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1656a34939Shaad */
1756a34939Shaad
1856a34939Shaad #include "dmlib.h"
1956a34939Shaad
2056a34939Shaad #include <sys/file.h>
2156a34939Shaad #include <fcntl.h>
2256a34939Shaad #include <dirent.h>
2356a34939Shaad
24*912a040bShaad /*
25*912a040bShaad * Created directories permissions are controled by umask values and
26*912a040bShaad * they should be set by api user before calling this function.
27*912a040bShaad * Changing directory owners is also left on caller.
28*912a040bShaad */
_create_dir_recursive(const char * dir)2956a34939Shaad static int _create_dir_recursive(const char *dir)
3056a34939Shaad {
3156a34939Shaad char *orig, *s;
3256a34939Shaad int rc, r = 0;
3356a34939Shaad
3456a34939Shaad log_verbose("Creating directory \"%s\"", dir);
3556a34939Shaad /* Create parent directories */
3656a34939Shaad orig = s = dm_strdup(dir);
3756a34939Shaad while ((s = strchr(s, '/')) != NULL) {
3856a34939Shaad *s = '\0';
3956a34939Shaad if (*orig) {
4056a34939Shaad rc = mkdir(orig, 0777);
4156a34939Shaad if (rc < 0 && errno != EEXIST) {
4256a34939Shaad if (errno != EROFS)
4356a34939Shaad log_sys_error("mkdir", orig);
4456a34939Shaad goto out;
4556a34939Shaad }
4656a34939Shaad }
4756a34939Shaad *s++ = '/';
4856a34939Shaad }
4956a34939Shaad
5056a34939Shaad /* Create final directory */
5156a34939Shaad rc = mkdir(dir, 0777);
5256a34939Shaad if (rc < 0 && errno != EEXIST) {
5356a34939Shaad if (errno != EROFS)
5456a34939Shaad log_sys_error("mkdir", orig);
5556a34939Shaad goto out;
5656a34939Shaad }
5756a34939Shaad
5856a34939Shaad r = 1;
5956a34939Shaad out:
6056a34939Shaad dm_free(orig);
6156a34939Shaad return r;
6256a34939Shaad }
6356a34939Shaad
dm_create_dir(const char * dir)6456a34939Shaad int dm_create_dir(const char *dir)
6556a34939Shaad {
6656a34939Shaad struct stat info;
6756a34939Shaad
6856a34939Shaad if (!*dir)
6956a34939Shaad return 1;
7056a34939Shaad
7156a34939Shaad if (stat(dir, &info) < 0)
7256a34939Shaad return _create_dir_recursive(dir);
7356a34939Shaad
7456a34939Shaad if (S_ISDIR(info.st_mode))
7556a34939Shaad return 1;
7656a34939Shaad
7756a34939Shaad log_error("Directory \"%s\" not found", dir);
7856a34939Shaad return 0;
7956a34939Shaad }
8056a34939Shaad
dm_fclose(FILE * stream)8156a34939Shaad int dm_fclose(FILE *stream)
8256a34939Shaad {
8356a34939Shaad int prev_fail = ferror(stream);
8456a34939Shaad int fclose_fail = fclose(stream);
8556a34939Shaad
8656a34939Shaad /* If there was a previous failure, but fclose succeeded,
8756a34939Shaad clear errno, since ferror does not set it, and its value
8856a34939Shaad may be unrelated to the ferror-reported failure. */
8956a34939Shaad if (prev_fail && !fclose_fail)
9056a34939Shaad errno = 0;
9156a34939Shaad
9256a34939Shaad return prev_fail || fclose_fail ? EOF : 0;
9356a34939Shaad }
94