xref: /netbsd-src/external/gpl2/lvm2/dist/libdm/libdm-file.c (revision 912a040b47adaee3e4d8d304ef66a69fff663934)
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