Loop.cpp revision d31e380bd9689dd9629b510ffe324707e261b439
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#define LOG_TAG "Vold" 27 28#include <cutils/log.h> 29 30#include "Loop.h" 31 32int Loop::lookupActive(const char *loopFile, char *buffer, size_t len) { 33 int i; 34 int fd; 35 char filename[256]; 36 37 memset(buffer, 0, len); 38 39 for (i = 0; i < LOOP_MAX; i++) { 40 struct loop_info li; 41 int rc; 42 43 sprintf(filename, "/dev/block/loop%d", i); 44 45 if ((fd = open(filename, O_RDWR)) < 0) { 46 if (errno != ENOENT) { 47 LOGE("Unable to open %s (%s)", filename, strerror(errno)); 48 } 49 return -1; 50 } 51 52 rc = ioctl(fd, LOOP_GET_STATUS, &li); 53 close(fd); 54 if (rc < 0 && errno == ENXIO) { 55 continue; 56 break; 57 } 58 59 if (rc < 0) { 60 LOGE("Unable to get loop status for %s (%s)", filename, 61 strerror(errno)); 62 return -1; 63 } 64 if (!strncmp(li.lo_name, loopFile, LO_NAME_SIZE)) { 65 break; 66 } 67 } 68 69 if (i == LOOP_MAX) { 70 errno = ENOENT; 71 return -1; 72 } 73 strncpy(buffer, filename, len -1); 74 return 0; 75} 76 77int Loop::create(const char *loopFile, char *loopDeviceBuffer, size_t len) { 78 int i; 79 int fd; 80 char filename[256]; 81 82 for (i = 0; i < LOOP_MAX; i++) { 83 struct loop_info li; 84 int rc; 85 86 sprintf(filename, "/dev/block/loop%d", i); 87 88 /* 89 * The kernel starts us off with 8 loop nodes, but more 90 * are created on-demand if needed. 91 */ 92 mode_t mode = 0660 | S_IFBLK; 93 unsigned int dev = (0xff & i) | ((i << 12) & 0xfff00000) | (7 << 8); 94 if (mknod(filename, mode, dev) < 0) { 95 if (errno != EEXIST) { 96 LOGE("Error creating loop device node (%s)", strerror(errno)); 97 return -1; 98 } 99 } 100 101 if ((fd = open(filename, O_RDWR)) < 0) { 102 LOGE("Unable to open %s (%s)", filename, strerror(errno)); 103 return -1; 104 } 105 106 rc = ioctl(fd, LOOP_GET_STATUS, &li); 107 if (rc < 0 && errno == ENXIO) 108 break; 109 110 close(fd); 111 112 if (rc < 0) { 113 LOGE("Unable to get loop status for %s (%s)", filename, 114 strerror(errno)); 115 return -1; 116 } 117 } 118 119 if (i == LOOP_MAX) { 120 LOGE("Exhausted all loop devices"); 121 errno = ENOSPC; 122 return -1; 123 } 124 125 strncpy(loopDeviceBuffer, filename, len -1); 126 127 int file_fd; 128 129 if ((file_fd = open(loopFile, O_RDWR)) < 0) { 130 LOGE("Unable to open %s (%s)", loopFile, strerror(errno)); 131 close(fd); 132 return -1; 133 } 134 135 if (ioctl(fd, LOOP_SET_FD, file_fd) < 0) { 136 LOGE("Error setting up loopback interface (%s)", strerror(errno)); 137 close(file_fd); 138 close(fd); 139 return -1; 140 } 141 142 struct loop_info li; 143 144 memset(&li, 0, sizeof(li)); 145 strncpy(li.lo_name, loopFile, LO_NAME_SIZE); 146 147 if (ioctl(fd, LOOP_SET_STATUS, &li) < 0) { 148 LOGE("Error setting loopback status (%s)", strerror(errno)); 149 close(file_fd); 150 close(fd); 151 return -1; 152 } 153 154 close(fd); 155 close(file_fd); 156 157 return 0; 158} 159 160int Loop::destroyByDevice(const char *loopDevice) { 161 int device_fd; 162 163 device_fd = open(loopDevice, O_RDONLY); 164 if (device_fd < 0) { 165 LOGE("Failed to open loop (%d)", errno); 166 return -1; 167 } 168 169 if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) { 170 LOGE("Failed to destroy loop (%d)", errno); 171 close(device_fd); 172 return -1; 173 } 174 175 close(device_fd); 176 return 0; 177} 178 179int Loop::destroyByFile(const char *loopFile) { 180 errno = ENOSYS; 181 return -1; 182} 183 184int Loop::createImageFile(const char *file, unsigned int numSectors) { 185 int fd; 186 187 LOGD("Creating image file %s (%u sectors)", file, numSectors); 188 189 if ((fd = creat(file, 0600)) < 0) { 190 LOGE("Error creating imagefile (%s)", strerror(errno)); 191 return -1; 192 } 193 194 if (ftruncate(fd, numSectors * 512) < 0) { 195 LOGE("Error truncating imagefile (%s)", strerror(errno)); 196 close(fd); 197 return -1; 198 } 199 close(fd); 200 return 0; 201} 202