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