|  | 
 | /* | 
 |  * Copyright (C) 2008 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #include <stdlib.h> | 
 | #include <string.h> | 
 | #include <dirent.h> | 
 | #include <errno.h> | 
 |  | 
 | #include <sys/types.h> | 
 |  | 
 | #include "vold.h" | 
 | #include "media.h" | 
 |  | 
 | static media_list_t *list_root = NULL; | 
 |  | 
 | media_t *media_create(char *devpath, char *name, char *serial, media_type_t type) | 
 | { | 
 |     media_list_t *list_entry; | 
 |     media_t *new; | 
 |  | 
 |     if (!(new = malloc(sizeof(media_t)))) | 
 |         return NULL; | 
 |  | 
 |     memset(new, 0, sizeof(media_t)); | 
 |  | 
 |     if (!(list_entry = malloc(sizeof(media_list_t)))) { | 
 |         free(new); | 
 |         return NULL; | 
 |     } | 
 |     list_entry->media = new; | 
 |     list_entry->next = NULL; | 
 |  | 
 |     if (!list_root) | 
 |         list_root = list_entry; | 
 |     else { | 
 |         media_list_t *list_scan = list_root; | 
 |         while(list_scan->next) | 
 |             list_scan = list_scan->next; | 
 |         list_scan->next = list_entry; | 
 |     } | 
 |       | 
 |     new->devpath = strdup(devpath); | 
 |     new->name = strdup(name); | 
 |     if (!serial) | 
 |         new->serial = 0; | 
 |     else | 
 |         new->serial = strtoul(serial, NULL, 0); | 
 |  | 
 |     new->media_type = type; | 
 |  | 
 |     return new; | 
 | } | 
 |  | 
 | void media_destroy(media_t *media) | 
 | { | 
 |     media_list_t *list_next; | 
 |  | 
 |     if (list_root->media == media) { | 
 |         list_next = list_root->next; | 
 |         free(list_root); | 
 |         list_root = list_next; | 
 |     } else { | 
 |         media_list_t *list_scan = list_root; | 
 |         while (list_scan->next->media != media) | 
 |             list_scan = list_scan -> next; | 
 |         list_next = list_scan->next->next; | 
 |         free(list_scan->next); | 
 |         list_scan->next = list_next; | 
 |     } | 
 |  | 
 |     free(media->devpath); | 
 |     free(media->name); | 
 |  | 
 |     while(media->devs) | 
 |         media_remove_blkdev(media, media->devs->dev); | 
 |     free(media); | 
 | } | 
 |  | 
 | media_t *media_lookup_by_path(char *devpath, boolean fuzzy_match) | 
 | { | 
 |     media_list_t *list_scan = list_root; | 
 |  | 
 |     while (list_scan) { | 
 |         if (fuzzy_match) { | 
 |             if (!strncmp(list_scan->media->devpath, devpath, strlen(devpath))) | 
 |                 return list_scan->media; | 
 |         } else { | 
 |             if (!strcmp(list_scan->media->devpath, devpath)) | 
 |                 return list_scan->media; | 
 |         } | 
 |         list_scan = list_scan->next; | 
 |     } | 
 | #if DEBUG_MEDIA | 
 |     LOG_VOL("media_lookup_by_path(): No media found @ %s", devpath); | 
 | #endif | 
 |     return NULL; | 
 | } | 
 |  | 
 | int media_add_blkdev(media_t *card, blkdev_t *dev) | 
 | { | 
 |     blkdev_list_t *list_entry; | 
 |  | 
 |     if (!(list_entry = malloc(sizeof(blkdev_list_t)))) | 
 |         return -ENOMEM; | 
 |      | 
 |     list_entry->next = NULL; | 
 |     list_entry->dev = dev; | 
 |     if (!card->devs) | 
 |         card->devs = list_entry; | 
 |     else { | 
 |         blkdev_list_t *scan = card->devs; | 
 |  | 
 |         while(scan->next) | 
 |             scan = scan->next; | 
 |  | 
 |         scan->next = list_entry; | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | void media_remove_blkdev(media_t *card, blkdev_t *dev) | 
 | { | 
 |     if (card->devs->dev == dev) | 
 |         card->devs = card->devs->next; | 
 |     else { | 
 |         blkdev_list_t *scan = card->devs; | 
 |         while (scan->next->dev != dev) | 
 |             scan = scan -> next; | 
 |         blkdev_list_t *next = scan->next->next; | 
 |         free(scan->next); | 
 |         scan->next = next; | 
 |     } | 
 | } | 
 |  | 
 | media_t *media_lookup_by_dev(blkdev_t *dev) | 
 | { | 
 |     media_list_t *media_scan = list_root; | 
 |  | 
 |     while (media_scan) { | 
 |         blkdev_list_t *blk_scan = media_scan->media->devs; | 
 |         while (blk_scan) { | 
 |             if (blk_scan->dev == dev) | 
 |                 return media_scan->media; | 
 |             blk_scan = blk_scan->next; | 
 |         } | 
 |         media_scan = media_scan->next; | 
 |     } | 
 |     return NULL; | 
 | } |