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