1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <fcntl.h> 20 #include <unistd.h> 21 #include <errno.h> 22 #include <string.h> 23 24 #include <sys/mount.h> 25 #include <sys/types.h> 26 #include <sys/stat.h> 27 #include <sys/ioctl.h> 28 29 #include <linux/kdev_t.h> 30 31 #define LOG_TAG "Vold" 32 33 #include <cutils/log.h> 34 35 #include <sysutils/SocketClient.h> 36 #include "Loop.h" 37 #include "Asec.h" 38 39 int Loop::dumpState(SocketClient *c) { 40 int i; 41 int fd; 42 char filename[256]; 43 44 for (i = 0; i < LOOP_MAX; i++) { 45 struct loop_info64 li; 46 int rc; 47 48 sprintf(filename, "/dev/block/loop%d", i); 49 50 if ((fd = open(filename, O_RDWR)) < 0) { 51 if (errno != ENOENT) { 52 SLOGE("Unable to open %s (%s)", filename, strerror(errno)); 53 } else { 54 continue; 55 } 56 return -1; 57 } 58 59 rc = ioctl(fd, LOOP_GET_STATUS64, &li); 60 close(fd); 61 if (rc < 0 && errno == ENXIO) { 62 continue; 63 } 64 65 if (rc < 0) { 66 SLOGE("Unable to get loop status for %s (%s)", filename, 67 strerror(errno)); 68 return -1; 69 } 70 char *tmp = NULL; 71 asprintf(&tmp, "%s %d %lld:%lld %llu %lld:%lld %lld 0x%x {%s} {%s}", filename, li.lo_number, 72 MAJOR(li.lo_device), MINOR(li.lo_device), li.lo_inode, MAJOR(li.lo_rdevice), 73 MINOR(li.lo_rdevice), li.lo_offset, li.lo_flags, li.lo_crypt_name, 74 li.lo_file_name); 75 c->sendMsg(0, tmp, false); 76 free(tmp); 77 } 78 return 0; 79 } 80 81 int Loop::lookupActive(const char *id, char *buffer, size_t len) { 82 int i; 83 int fd; 84 char filename[256]; 85 86 memset(buffer, 0, len); 87 88 for (i = 0; i < LOOP_MAX; i++) { 89 struct loop_info64 li; 90 int rc; 91 92 sprintf(filename, "/dev/block/loop%d", i); 93 94 if ((fd = open(filename, O_RDWR)) < 0) { 95 if (errno != ENOENT) { 96 SLOGE("Unable to open %s (%s)", filename, strerror(errno)); 97 } else { 98 continue; 99 } 100 return -1; 101 } 102 103 rc = ioctl(fd, LOOP_GET_STATUS64, &li); 104 close(fd); 105 if (rc < 0 && errno == ENXIO) { 106 continue; 107 } 108 109 if (rc < 0) { 110 SLOGE("Unable to get loop status for %s (%s)", filename, 111 strerror(errno)); 112 return -1; 113 } 114 if (!strncmp((const char*) li.lo_crypt_name, id, LO_NAME_SIZE)) { 115 break; 116 } 117 } 118 119 if (i == LOOP_MAX) { 120 errno = ENOENT; 121 return -1; 122 } 123 strncpy(buffer, filename, len -1); 124 return 0; 125 } 126 127 int Loop::create(const char *id, const char *loopFile, char *loopDeviceBuffer, size_t len) { 128 int i; 129 int fd; 130 char filename[256]; 131 132 for (i = 0; i < LOOP_MAX; i++) { 133 struct loop_info64 li; 134 int rc; 135 136 sprintf(filename, "/dev/block/loop%d", i); 137 138 /* 139 * The kernel starts us off with 8 loop nodes, but more 140 * are created on-demand if needed. 141 */ 142 mode_t mode = 0660 | S_IFBLK; 143 unsigned int dev = (0xff & i) | ((i << 12) & 0xfff00000) | (7 << 8); 144 if (mknod(filename, mode, dev) < 0) { 145 if (errno != EEXIST) { 146 SLOGE("Error creating loop device node (%s)", strerror(errno)); 147 return -1; 148 } 149 } 150 151 if ((fd = open(filename, O_RDWR)) < 0) { 152 SLOGE("Unable to open %s (%s)", filename, strerror(errno)); 153 return -1; 154 } 155 156 rc = ioctl(fd, LOOP_GET_STATUS64, &li); 157 if (rc < 0 && errno == ENXIO) 158 break; 159 160 close(fd); 161 162 if (rc < 0) { 163 SLOGE("Unable to get loop status for %s (%s)", filename, 164 strerror(errno)); 165 return -1; 166 } 167 } 168 169 if (i == LOOP_MAX) { 170 SLOGE("Exhausted all loop devices"); 171 errno = ENOSPC; 172 return -1; 173 } 174 175 strncpy(loopDeviceBuffer, filename, len -1); 176 177 int file_fd; 178 179 if ((file_fd = open(loopFile, O_RDWR)) < 0) { 180 SLOGE("Unable to open %s (%s)", loopFile, strerror(errno)); 181 close(fd); 182 return -1; 183 } 184 185 if (ioctl(fd, LOOP_SET_FD, file_fd) < 0) { 186 SLOGE("Error setting up loopback interface (%s)", strerror(errno)); 187 close(file_fd); 188 close(fd); 189 return -1; 190 } 191 192 struct loop_info64 li; 193 194 memset(&li, 0, sizeof(li)); 195 strlcpy((char*) li.lo_crypt_name, id, LO_NAME_SIZE); 196 strlcpy((char*) li.lo_file_name, loopFile, LO_NAME_SIZE); 197 198 if (ioctl(fd, LOOP_SET_STATUS64, &li) < 0) { 199 SLOGE("Error setting loopback status (%s)", strerror(errno)); 200 close(file_fd); 201 close(fd); 202 return -1; 203 } 204 205 close(fd); 206 close(file_fd); 207 208 return 0; 209 } 210 211 int Loop::destroyByDevice(const char *loopDevice) { 212 int device_fd; 213 214 device_fd = open(loopDevice, O_RDONLY); 215 if (device_fd < 0) { 216 SLOGE("Failed to open loop (%d)", errno); 217 return -1; 218 } 219 220 if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) { 221 SLOGE("Failed to destroy loop (%d)", errno); 222 close(device_fd); 223 return -1; 224 } 225 226 close(device_fd); 227 return 0; 228 } 229 230 int Loop::destroyByFile(const char *loopFile) { 231 errno = ENOSYS; 232 return -1; 233 } 234 235 int Loop::createImageFile(const char *file, unsigned int numSectors) { 236 int fd; 237 238 if ((fd = creat(file, 0600)) < 0) { 239 SLOGE("Error creating imagefile (%s)", strerror(errno)); 240 return -1; 241 } 242 243 if (ftruncate(fd, numSectors * 512) < 0) { 244 SLOGE("Error truncating imagefile (%s)", strerror(errno)); 245 close(fd); 246 return -1; 247 } 248 close(fd); 249 return 0; 250 } 251 252 int Loop::lookupInfo(const char *loopDevice, struct asec_superblock *sb, unsigned int *nr_sec) { 253 int fd; 254 struct asec_superblock buffer; 255 256 if ((fd = open(loopDevice, O_RDONLY)) < 0) { 257 SLOGE("Failed to open loopdevice (%s)", strerror(errno)); 258 destroyByDevice(loopDevice); 259 return -1; 260 } 261 262 if (ioctl(fd, BLKGETSIZE, nr_sec)) { 263 SLOGE("Failed to get loop size (%s)", strerror(errno)); 264 destroyByDevice(loopDevice); 265 close(fd); 266 return -1; 267 } 268 269 /* 270 * Try to read superblock. 271 */ 272 memset(&buffer, 0, sizeof(struct asec_superblock)); 273 if (lseek(fd, ((*nr_sec - 1) * 512), SEEK_SET) < 0) { 274 SLOGE("lseek failed (%s)", strerror(errno)); 275 close(fd); 276 destroyByDevice(loopDevice); 277 return -1; 278 } 279 if (read(fd, &buffer, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) { 280 SLOGE("superblock read failed (%s)", strerror(errno)); 281 close(fd); 282 destroyByDevice(loopDevice); 283 return -1; 284 } 285 close(fd); 286 287 /* 288 * Superblock successfully read. Copy to caller's struct. 289 */ 290 memcpy(sb, &buffer, sizeof(struct asec_superblock)); 291 return 0; 292 } 293