Home | History | Annotate | Download | only in vold
      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 <android-base/logging.h>
     36 #include <android-base/stringprintf.h>
     37 #include <android-base/unique_fd.h>
     38 
     39 #include <sysutils/SocketClient.h>
     40 #include "Loop.h"
     41 #include "Asec.h"
     42 #include "VoldUtil.h"
     43 #include "sehandle.h"
     44 
     45 using android::base::StringPrintf;
     46 using android::base::unique_fd;
     47 
     48 int Loop::dumpState(SocketClient *c) {
     49     int i;
     50     int fd;
     51     char filename[256];
     52 
     53     for (i = 0; i < LOOP_MAX; i++) {
     54         struct loop_info64 li;
     55         int rc;
     56 
     57         snprintf(filename, sizeof(filename), "/dev/block/loop%d", i);
     58 
     59         if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) {
     60             if (errno != ENOENT) {
     61                 SLOGE("Unable to open %s (%s)", filename, strerror(errno));
     62             } else {
     63                 continue;
     64             }
     65             return -1;
     66         }
     67 
     68         rc = ioctl(fd, LOOP_GET_STATUS64, &li);
     69         close(fd);
     70         if (rc < 0 && errno == ENXIO) {
     71             continue;
     72         }
     73 
     74         if (rc < 0) {
     75             SLOGE("Unable to get loop status for %s (%s)", filename,
     76                  strerror(errno));
     77             return -1;
     78         }
     79         char *tmp = NULL;
     80         asprintf(&tmp, "%s %d %lld:%lld %llu %lld:%lld %lld 0x%x {%s} {%s}", filename, li.lo_number,
     81                 MAJOR(li.lo_device), MINOR(li.lo_device), li.lo_inode, MAJOR(li.lo_rdevice),
     82                         MINOR(li.lo_rdevice), li.lo_offset, li.lo_flags, li.lo_crypt_name,
     83                         li.lo_file_name);
     84         c->sendMsg(0, tmp, false);
     85         free(tmp);
     86     }
     87     return 0;
     88 }
     89 
     90 int Loop::lookupActive(const char *id, char *buffer, size_t len) {
     91     int i;
     92     int fd;
     93     char filename[256];
     94 
     95     memset(buffer, 0, len);
     96 
     97     for (i = 0; i < LOOP_MAX; i++) {
     98         struct loop_info64 li;
     99         int rc;
    100 
    101         snprintf(filename, sizeof(filename), "/dev/block/loop%d", i);
    102 
    103         if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) {
    104             if (errno != ENOENT) {
    105                 SLOGE("Unable to open %s (%s)", filename, strerror(errno));
    106             } else {
    107                 continue;
    108             }
    109             return -1;
    110         }
    111 
    112         rc = ioctl(fd, LOOP_GET_STATUS64, &li);
    113         if (rc < 0 && errno == ENXIO) {
    114             close(fd);
    115             continue;
    116         }
    117         close(fd);
    118 
    119         if (rc < 0) {
    120             SLOGE("Unable to get loop status for %s (%s)", filename,
    121                  strerror(errno));
    122             return -1;
    123         }
    124         if (!strncmp((const char*) li.lo_crypt_name, id, LO_NAME_SIZE)) {
    125             break;
    126         }
    127     }
    128 
    129     if (i == LOOP_MAX) {
    130         errno = ENOENT;
    131         return -1;
    132     }
    133     strlcpy(buffer, filename, len);
    134     return 0;
    135 }
    136 
    137 int Loop::create(const char *id, const char *loopFile, char *loopDeviceBuffer, size_t len) {
    138     int i;
    139     int fd;
    140     char filename[256];
    141 
    142     for (i = 0; i < LOOP_MAX; i++) {
    143         struct loop_info64 li;
    144         int rc;
    145         char *secontext = NULL;
    146 
    147         snprintf(filename, sizeof(filename), "/dev/block/loop%d", i);
    148 
    149         /*
    150          * The kernel starts us off with 8 loop nodes, but more
    151          * are created on-demand if needed.
    152          */
    153         mode_t mode = 0660 | S_IFBLK;
    154         unsigned int dev = (0xff & i) | ((i << 12) & 0xfff00000) | (7 << 8);
    155 
    156         if (sehandle) {
    157             rc = selabel_lookup(sehandle, &secontext, filename, S_IFBLK);
    158             if (rc == 0)
    159                 setfscreatecon(secontext);
    160         }
    161 
    162         if (mknod(filename, mode, dev) < 0) {
    163             if (errno != EEXIST) {
    164                 int sverrno = errno;
    165                 SLOGE("Error creating loop device node (%s)", strerror(errno));
    166                 if (secontext) {
    167                     freecon(secontext);
    168                     setfscreatecon(NULL);
    169                 }
    170                 errno = sverrno;
    171                 return -1;
    172             }
    173         }
    174         if (secontext) {
    175             freecon(secontext);
    176             setfscreatecon(NULL);
    177         }
    178 
    179         if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) {
    180             SLOGE("Unable to open %s (%s)", filename, strerror(errno));
    181             return -1;
    182         }
    183 
    184         rc = ioctl(fd, LOOP_GET_STATUS64, &li);
    185         if (rc < 0 && errno == ENXIO)
    186             break;
    187 
    188         close(fd);
    189 
    190         if (rc < 0) {
    191             SLOGE("Unable to get loop status for %s (%s)", filename,
    192                  strerror(errno));
    193             return -1;
    194         }
    195     }
    196 
    197     if (i == LOOP_MAX) {
    198         SLOGE("Exhausted all loop devices");
    199         errno = ENOSPC;
    200         return -1;
    201     }
    202 
    203     strlcpy(loopDeviceBuffer, filename, len);
    204 
    205     int file_fd;
    206 
    207     if ((file_fd = open(loopFile, O_RDWR | O_CLOEXEC)) < 0) {
    208         SLOGE("Unable to open %s (%s)", loopFile, strerror(errno));
    209         close(fd);
    210         return -1;
    211     }
    212 
    213     if (ioctl(fd, LOOP_SET_FD, file_fd) < 0) {
    214         SLOGE("Error setting up loopback interface (%s)", strerror(errno));
    215         close(file_fd);
    216         close(fd);
    217         return -1;
    218     }
    219 
    220     struct loop_info64 li;
    221 
    222     memset(&li, 0, sizeof(li));
    223     strlcpy((char*) li.lo_crypt_name, id, LO_NAME_SIZE);
    224     strlcpy((char*) li.lo_file_name, loopFile, LO_NAME_SIZE);
    225 
    226     if (ioctl(fd, LOOP_SET_STATUS64, &li) < 0) {
    227         SLOGE("Error setting loopback status (%s)", strerror(errno));
    228         close(file_fd);
    229         close(fd);
    230         return -1;
    231     }
    232 
    233     close(fd);
    234     close(file_fd);
    235 
    236     return 0;
    237 }
    238 
    239 int Loop::create(const std::string& target, std::string& out_device) {
    240     unique_fd ctl_fd(open("/dev/loop-control", O_RDWR | O_CLOEXEC));
    241     if (ctl_fd.get() == -1) {
    242         PLOG(ERROR) << "Failed to open loop-control";
    243         return -errno;
    244     }
    245 
    246     int num = ioctl(ctl_fd.get(), LOOP_CTL_GET_FREE);
    247     if (num == -1) {
    248         PLOG(ERROR) << "Failed LOOP_CTL_GET_FREE";
    249         return -errno;
    250     }
    251 
    252     out_device = StringPrintf("/dev/block/loop%d", num);
    253 
    254     unique_fd target_fd(open(target.c_str(), O_RDWR | O_CLOEXEC));
    255     if (target_fd.get() == -1) {
    256         PLOG(ERROR) << "Failed to open " << target;
    257         return -errno;
    258     }
    259     unique_fd device_fd(open(out_device.c_str(), O_RDWR | O_CLOEXEC));
    260     if (device_fd.get() == -1) {
    261         PLOG(ERROR) << "Failed to open " << out_device;
    262         return -errno;
    263     }
    264 
    265     if (ioctl(device_fd.get(), LOOP_SET_FD, target_fd.get()) == -1) {
    266         PLOG(ERROR) << "Failed to LOOP_SET_FD";
    267         return -errno;
    268     }
    269 
    270     return 0;
    271 }
    272 
    273 int Loop::destroyByDevice(const char *loopDevice) {
    274     int device_fd;
    275 
    276     device_fd = open(loopDevice, O_RDONLY | O_CLOEXEC);
    277     if (device_fd < 0) {
    278         SLOGE("Failed to open loop (%d)", errno);
    279         return -1;
    280     }
    281 
    282     if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) {
    283         SLOGE("Failed to destroy loop (%d)", errno);
    284         close(device_fd);
    285         return -1;
    286     }
    287 
    288     close(device_fd);
    289     return 0;
    290 }
    291 
    292 int Loop::destroyByFile(const char * /*loopFile*/) {
    293     errno = ENOSYS;
    294     return -1;
    295 }
    296 
    297 int Loop::createImageFile(const char *file, unsigned long numSectors) {
    298     unique_fd fd(open(file, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0600));
    299     if (fd.get() == -1) {
    300         PLOG(ERROR) << "Failed to create image " << file;
    301         return -errno;
    302     }
    303     if (fallocate(fd.get(), 0, 0, numSectors * 512) == -1) {
    304         PLOG(WARNING) << "Failed to fallocate; falling back to ftruncate";
    305         if (ftruncate(fd, numSectors * 512) == -1) {
    306             PLOG(ERROR) << "Failed to ftruncate";
    307             return -errno;
    308         }
    309     }
    310     return 0;
    311 }
    312 
    313 int Loop::resizeImageFile(const char *file, unsigned long numSectors) {
    314     int fd;
    315 
    316     if ((fd = open(file, O_RDWR | O_CLOEXEC)) < 0) {
    317         SLOGE("Error opening imagefile (%s)", strerror(errno));
    318         return -1;
    319     }
    320 
    321     SLOGD("Attempting to increase size of %s to %lu sectors.", file, numSectors);
    322 
    323     if (fallocate(fd, 0, 0, numSectors * 512)) {
    324         if (errno == ENOSYS || errno == ENOTSUP) {
    325             SLOGW("fallocate not found. Falling back to ftruncate.");
    326             if (ftruncate(fd, numSectors * 512) < 0) {
    327                 SLOGE("Error truncating imagefile (%s)", strerror(errno));
    328                 close(fd);
    329                 return -1;
    330             }
    331         } else {
    332             SLOGE("Error allocating space (%s)", strerror(errno));
    333             close(fd);
    334             return -1;
    335         }
    336     }
    337     close(fd);
    338     return 0;
    339 }
    340 
    341 int Loop::lookupInfo(const char *loopDevice, struct asec_superblock *sb, unsigned long *nr_sec) {
    342     int fd;
    343     struct asec_superblock buffer;
    344 
    345     if ((fd = open(loopDevice, O_RDONLY | O_CLOEXEC)) < 0) {
    346         SLOGE("Failed to open loopdevice (%s)", strerror(errno));
    347         destroyByDevice(loopDevice);
    348         return -1;
    349     }
    350 
    351     get_blkdev_size(fd, nr_sec);
    352     if (*nr_sec == 0) {
    353         SLOGE("Failed to get loop size (%s)", strerror(errno));
    354         destroyByDevice(loopDevice);
    355         close(fd);
    356         return -1;
    357     }
    358 
    359     /*
    360      * Try to read superblock.
    361      */
    362     memset(&buffer, 0, sizeof(struct asec_superblock));
    363     if (lseek(fd, ((*nr_sec - 1) * 512), SEEK_SET) < 0) {
    364         SLOGE("lseek failed (%s)", strerror(errno));
    365         close(fd);
    366         destroyByDevice(loopDevice);
    367         return -1;
    368     }
    369     if (read(fd, &buffer, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) {
    370         SLOGE("superblock read failed (%s)", strerror(errno));
    371         close(fd);
    372         destroyByDevice(loopDevice);
    373         return -1;
    374     }
    375     close(fd);
    376 
    377     /*
    378      * Superblock successfully read. Copy to caller's struct.
    379      */
    380     memcpy(sb, &buffer, sizeof(struct asec_superblock));
    381     return 0;
    382 }
    383