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/types.h> 25 #include <sys/stat.h> 26 #include <sys/ioctl.h> 27 28 #include <linux/kdev_t.h> 29 30 #define LOG_TAG "Vold" 31 32 #include <cutils/log.h> 33 34 #include <sysutils/SocketClient.h> 35 #include "Loop.h" 36 37 int Loop::dumpState(SocketClient *c) { 38 int i; 39 int fd; 40 char filename[256]; 41 42 for (i = 0; i < LOOP_MAX; i++) { 43 struct loop_info64 li; 44 int rc; 45 46 sprintf(filename, "/dev/block/loop%d", i); 47 48 if ((fd = open(filename, O_RDWR)) < 0) { 49 if (errno != ENOENT) { 50 SLOGE("Unable to open %s (%s)", filename, strerror(errno)); 51 } else { 52 continue; 53 } 54 return -1; 55 } 56 57 rc = ioctl(fd, LOOP_GET_STATUS64, &li); 58 close(fd); 59 if (rc < 0 && errno == ENXIO) { 60 continue; 61 } 62 63 if (rc < 0) { 64 SLOGE("Unable to get loop status for %s (%s)", filename, 65 strerror(errno)); 66 return -1; 67 } 68 char *tmp = NULL; 69 asprintf(&tmp, "%s %d %lld:%lld %llu %lld:%lld %lld 0x%x {%s} {%s}", filename, li.lo_number, 70 MAJOR(li.lo_device), MINOR(li.lo_device), li.lo_inode, MAJOR(li.lo_rdevice), 71 MINOR(li.lo_rdevice), li.lo_offset, li.lo_flags, li.lo_crypt_name, 72 li.lo_file_name); 73 c->sendMsg(0, tmp, false); 74 free(tmp); 75 } 76 return 0; 77 } 78 79 int Loop::lookupActive(const char *id, char *buffer, size_t len) { 80 int i; 81 int fd; 82 char filename[256]; 83 84 memset(buffer, 0, len); 85 86 for (i = 0; i < LOOP_MAX; i++) { 87 struct loop_info64 li; 88 int rc; 89 90 sprintf(filename, "/dev/block/loop%d", i); 91 92 if ((fd = open(filename, O_RDWR)) < 0) { 93 if (errno != ENOENT) { 94 SLOGE("Unable to open %s (%s)", filename, strerror(errno)); 95 } else { 96 continue; 97 } 98 return -1; 99 } 100 101 rc = ioctl(fd, LOOP_GET_STATUS64, &li); 102 close(fd); 103 if (rc < 0 && errno == ENXIO) { 104 continue; 105 } 106 107 if (rc < 0) { 108 SLOGE("Unable to get loop status for %s (%s)", filename, 109 strerror(errno)); 110 return -1; 111 } 112 if (!strncmp((const char*) li.lo_crypt_name, id, LO_NAME_SIZE)) { 113 break; 114 } 115 } 116 117 if (i == LOOP_MAX) { 118 errno = ENOENT; 119 return -1; 120 } 121 strncpy(buffer, filename, len -1); 122 return 0; 123 } 124 125 int Loop::create(const char *id, const char *loopFile, char *loopDeviceBuffer, size_t len) { 126 int i; 127 int fd; 128 char filename[256]; 129 130 for (i = 0; i < LOOP_MAX; i++) { 131 struct loop_info64 li; 132 int rc; 133 134 sprintf(filename, "/dev/block/loop%d", i); 135 136 /* 137 * The kernel starts us off with 8 loop nodes, but more 138 * are created on-demand if needed. 139 */ 140 mode_t mode = 0660 | S_IFBLK; 141 unsigned int dev = (0xff & i) | ((i << 12) & 0xfff00000) | (7 << 8); 142 if (mknod(filename, mode, dev) < 0) { 143 if (errno != EEXIST) { 144 SLOGE("Error creating loop device node (%s)", strerror(errno)); 145 return -1; 146 } 147 } 148 149 if ((fd = open(filename, O_RDWR)) < 0) { 150 SLOGE("Unable to open %s (%s)", filename, strerror(errno)); 151 return -1; 152 } 153 154 rc = ioctl(fd, LOOP_GET_STATUS64, &li); 155 if (rc < 0 && errno == ENXIO) 156 break; 157 158 close(fd); 159 160 if (rc < 0) { 161 SLOGE("Unable to get loop status for %s (%s)", filename, 162 strerror(errno)); 163 return -1; 164 } 165 } 166 167 if (i == LOOP_MAX) { 168 SLOGE("Exhausted all loop devices"); 169 errno = ENOSPC; 170 return -1; 171 } 172 173 strncpy(loopDeviceBuffer, filename, len -1); 174 175 int file_fd; 176 177 if ((file_fd = open(loopFile, O_RDWR)) < 0) { 178 SLOGE("Unable to open %s (%s)", loopFile, strerror(errno)); 179 close(fd); 180 return -1; 181 } 182 183 if (ioctl(fd, LOOP_SET_FD, file_fd) < 0) { 184 SLOGE("Error setting up loopback interface (%s)", strerror(errno)); 185 close(file_fd); 186 close(fd); 187 return -1; 188 } 189 190 struct loop_info64 li; 191 192 memset(&li, 0, sizeof(li)); 193 strlcpy((char*) li.lo_crypt_name, id, LO_NAME_SIZE); 194 strlcpy((char*) li.lo_file_name, loopFile, LO_NAME_SIZE); 195 196 if (ioctl(fd, LOOP_SET_STATUS64, &li) < 0) { 197 SLOGE("Error setting loopback status (%s)", strerror(errno)); 198 close(file_fd); 199 close(fd); 200 return -1; 201 } 202 203 close(fd); 204 close(file_fd); 205 206 return 0; 207 } 208 209 int Loop::destroyByDevice(const char *loopDevice) { 210 int device_fd; 211 212 device_fd = open(loopDevice, O_RDONLY); 213 if (device_fd < 0) { 214 SLOGE("Failed to open loop (%d)", errno); 215 return -1; 216 } 217 218 if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) { 219 SLOGE("Failed to destroy loop (%d)", errno); 220 close(device_fd); 221 return -1; 222 } 223 224 close(device_fd); 225 return 0; 226 } 227 228 int Loop::destroyByFile(const char *loopFile) { 229 errno = ENOSYS; 230 return -1; 231 } 232 233 int Loop::createImageFile(const char *file, unsigned int numSectors) { 234 int fd; 235 236 if ((fd = creat(file, 0600)) < 0) { 237 SLOGE("Error creating imagefile (%s)", strerror(errno)); 238 return -1; 239 } 240 241 if (ftruncate(fd, numSectors * 512) < 0) { 242 SLOGE("Error truncating imagefile (%s)", strerror(errno)); 243 close(fd); 244 return -1; 245 } 246 close(fd); 247 return 0; 248 } 249