diff options
Diffstat (limited to 'vold')
| -rw-r--r-- | vold/misc.c | 90 | ||||
| -rw-r--r-- | vold/uevent.c | 2 | ||||
| -rw-r--r-- | vold/volmgr.c | 37 |
3 files changed, 110 insertions, 19 deletions
diff --git a/vold/misc.c b/vold/misc.c index 951414c..b8e5957 100644 --- a/vold/misc.c +++ b/vold/misc.c @@ -49,8 +49,11 @@ void *read_file(char *filename, ssize_t *_size) /* slurp it into our buffer */ ret = read(fd, buffer, size); - if (ret != size) + if (ret != size) { + free(buffer); + buffer = NULL; goto bail; + } /* let the caller know how big it is */ *_size = size; @@ -59,33 +62,90 @@ bail: close(fd); return buffer; } -char *truncate_sysfs_path(char *path, int num_elements_to_remove, char *buffer) + +char *truncate_sysfs_path(char *path, int count, char *buffer, size_t bufflen) { - int i; + char* p; - strcpy(buffer, path); + strlcpy(buffer, path, bufflen); + p = buffer + strlen(buffer); - for (i = 0; i < num_elements_to_remove; i++) { - char *p = &buffer[strlen(buffer)-1]; + for ( ; count > 0; count-- ) { + while (p > buffer && p[-1] != '/') { + p--; + } + if (p == buffer) + break; - for (p = &buffer[strlen(buffer) -1]; *p != '/'; p--); - *p = '\0'; + p -= 1; } + p[0] = '\0'; return buffer; } -char *read_sysfs_var(char *buffer, size_t maxlen, char *devpath, char *var) +/* used to read the first line of a /sys file into a heap-allocated buffer + * this assumes that reading the file returns a list of zero-terminated strings, + * each could also have a terminating \n before the 0 + * + * returns NULL on error, of a new string on success, which must be freed by the + * caller. + */ +char *read_first_line_of(const char* filepath) { - char filename[255]; - char *p; + char *p, *q, *line; + size_t len; ssize_t sz; - sprintf(filename, "/sys%s/%s", devpath, var); - p = read_file(filename, &sz); - p[(strlen(p) - 1)] = '\0'; - strncpy(buffer, p, maxlen); + p = read_file((char*)filepath, &sz); + if (p == NULL) + goto FAIL; + + /* search end of first line */ + q = memchr(p, sz, '\0'); + if (q == NULL) + q = p + sz; /* let's be flexible */ + + len = (size_t)(q - p); /* compute line length */ + if (len == 0) + goto FAIL; + + if (p[len-1] == '\n') { /* strip trailing \n */ + len -= 1; + if (len == 0) + goto FAIL; + } + + line = malloc(len+1); + if (line == NULL) + goto FAIL; + + memcpy(line, p, len); + line[len] = 0; free(p); + + return line; + +FAIL: + if (p != NULL) + free(p); + + return NULL; +} + +char *read_sysfs_var(char *buffer, size_t maxlen, char *devpath, char *var) +{ + char filename[255], *line; + + snprintf(filename, sizeof filename, "/sys%s/%s", devpath, var); + + line = read_first_line_of(filename); + if (line == NULL) + return NULL; + + snprintf(buffer, maxlen, "%s", line); + free(line); + return buffer; } diff --git a/vold/uevent.c b/vold/uevent.c index 3b7e53b..b1a6944 100644 --- a/vold/uevent.c +++ b/vold/uevent.c @@ -72,7 +72,7 @@ static struct uevent_dispatch dispatch_table[] = { }; static boolean low_batt = false; -static boolean door_open = false; +static boolean door_open = true; int process_uevent_message(int socket) { diff --git a/vold/volmgr.c b/vold/volmgr.c index 0cec825..c3ce8d1 100644 --- a/vold/volmgr.c +++ b/vold/volmgr.c @@ -356,6 +356,7 @@ int volmgr_notify_eject(blkdev_t *dev, void (* cb) (blkdev_t *)) LOG_VOL("Volmgr notified of %d:%d eject", dev->major, dev->minor); volume_t *v; + int rc; // XXX: Partitioning support is going to need us to stop *all* // devices in this volume @@ -371,9 +372,38 @@ int volmgr_notify_eject(blkdev_t *dev, void (* cb) (blkdev_t *)) if (v->state == volstate_mounted || v->state == volstate_ums || - v->state == volstate_checking) + v->state == volstate_checking) { + volume_setstate(v, volstate_badremoval); - else if (v->state == volstate_formatting) { + + /* + * Stop any devmapper volumes which + * are using us as a source + * XXX: We may need to enforce stricter + * order here + */ + volume_t *dmvol = vol_root; + while (dmvol) { + if ((dmvol->media_type == media_devmapper) && + (dmvol->dm->src_type == dmsrc_loopback) && + (!strncmp(dmvol->dm->type_data.loop.loop_src, + v->mount_point, strlen(v->mount_point)))) { + + pthread_mutex_lock(&dmvol->lock); + if (dmvol->state != volstate_nomedia) { + rc = volmgr_shutdown_volume(dmvol, _cb_volstopped_for_devmapper_teardown, false); + if (rc != -EINPROGRESS) { + if (rc) + LOGE("unable to shutdown volume '%s'", v->mount_point); + pthread_mutex_unlock(&dmvol->lock); + } + } else + pthread_mutex_unlock(&dmvol->lock); + } + dmvol = dmvol->next; + } + + } else if (v->state == volstate_formatting) { /* * The device is being ejected due to * kernel disk revalidation. @@ -409,7 +439,8 @@ static void _cb_volume_stopped_for_eject(volume_t *v, void *arg) LOG_VOL("Volume %s has been stopped for eject", v->mount_point); #endif - eject_cb(v->dev); + if (eject_cb) + eject_cb(v->dev); v->dev = NULL; // Clear dev because its being ejected } |
