1/* 2 * Copyright (C) 2004-2005 Kay Sievers <kay.sievers@vrfy.org> 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License as published by the 6 * Free Software Foundation version 2 of the License. 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write to the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 * 17 */ 18 19 20#include <stdlib.h> 21#include <stdio.h> 22#include <stddef.h> 23#include <unistd.h> 24#include <fcntl.h> 25#include <errno.h> 26#include <ctype.h> 27#include <dirent.h> 28#include <sys/stat.h> 29#include <sys/mman.h> 30 31#include "udev.h" 32 33int create_path(const char *path) 34{ 35 char p[PATH_SIZE]; 36 char *pos; 37 struct stat stats; 38 39 strlcpy(p, path, sizeof(p)); 40 pos = strrchr(p, '/'); 41 if (pos == p || pos == NULL) 42 return 0; 43 44 while (pos[-1] == '/') 45 pos--; 46 pos[0] = '\0'; 47 48 dbg("stat '%s'", p); 49 if (stat(p, &stats) == 0 && (stats.st_mode & S_IFMT) == S_IFDIR) 50 return 0; 51 52 if (create_path (p) != 0) 53 return -1; 54 55 dbg("mkdir '%s'", p); 56 if (mkdir(p, 0755) == 0) 57 return 0; 58 if (errno == EEXIST) 59 if (stat(p, &stats) == 0 && (stats.st_mode & S_IFMT) == S_IFDIR) 60 return 0; 61 return -1; 62} 63 64int delete_path(const char *path) 65{ 66 char p[PATH_SIZE]; 67 char *pos; 68 int retval; 69 70 strcpy (p, path); 71 pos = strrchr(p, '/'); 72 if (pos == p || pos == NULL) 73 return 0; 74 75 while (1) { 76 *pos = '\0'; 77 pos = strrchr(p, '/'); 78 79 /* don't remove the last one */ 80 if ((pos == p) || (pos == NULL)) 81 break; 82 83 /* remove if empty */ 84 retval = rmdir(p); 85 if (errno == ENOENT) 86 retval = 0; 87 if (retval) { 88 if (errno == ENOTEMPTY) 89 return 0; 90 err("rmdir(%s) failed: %s", p, strerror(errno)); 91 break; 92 } 93 dbg("removed '%s'", p); 94 } 95 return 0; 96} 97 98/* Reset permissions on the device node, before unlinking it to make sure, 99 * that permisions of possible hard links will be removed too. 100 */ 101int unlink_secure(const char *filename) 102{ 103 int retval; 104 105 retval = chown(filename, 0, 0); 106 if (retval) 107 err("chown(%s, 0, 0) failed: %s", filename, strerror(errno)); 108 109 retval = chmod(filename, 0000); 110 if (retval) 111 err("chmod(%s, 0000) failed: %s", filename, strerror(errno)); 112 113 retval = unlink(filename); 114 if (errno == ENOENT) 115 retval = 0; 116 117 if (retval) 118 err("unlink(%s) failed: %s", filename, strerror(errno)); 119 120 return retval; 121} 122 123int file_map(const char *filename, char **buf, size_t *bufsize) 124{ 125 struct stat stats; 126 int fd; 127 128 fd = open(filename, O_RDONLY); 129 if (fd < 0) { 130 return -1; 131 } 132 133 if (fstat(fd, &stats) < 0) { 134 close(fd); 135 return -1; 136 } 137 138 *buf = mmap(NULL, stats.st_size, PROT_READ, MAP_SHARED, fd, 0); 139 if (*buf == MAP_FAILED) { 140 close(fd); 141 return -1; 142 } 143 *bufsize = stats.st_size; 144 145 close(fd); 146 147 return 0; 148} 149 150void file_unmap(void *buf, size_t bufsize) 151{ 152 munmap(buf, bufsize); 153} 154 155/* return number of chars until the next newline, skip escaped newline */ 156size_t buf_get_line(const char *buf, size_t buflen, size_t cur) 157{ 158 int escape = 0; 159 size_t count; 160 161 for (count = cur; count < buflen; count++) { 162 if (!escape && buf[count] == '\n') 163 break; 164 165 if (buf[count] == '\\') 166 escape = 1; 167 else 168 escape = 0; 169 } 170 171 return count - cur; 172} 173