⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 automount.c

📁 Android 一些工具
💻 C
📖 第 1 页 / 共 2 页
字号:
                }            } else if (mp->umsActive) {                SetBackingStore(mp, false);                if (mp->state == kUnmountingForUms)                {                    ClearRetries(mp, kMounted);                    NotifyMediaState(mp->mountPoint, MEDIA_MOUNTED, false);                }                else if (mp->state == kUnmounted)                {                    NotifyMediaState(mp->mountPoint, MEDIA_UNMOUNTED, false);                    RequestMount(mp);                }            }        }        mp = mp->next;    }}// called when USB mass storage connected state changesstatic void HandleMassStorageOnline(boolean connected){    if (connected != gMassStorageConnected)    {        gMassStorageConnected = connected;        SendMassStorageConnected(connected);                // we automatically reset to mass storage off after USB is connected        if (!connected)            gMassStorageEnabled = false;            MassStorageStateChanged();    }}// called when a new block device has been createdstatic void HandleMediaInserted(const char* device){    MountPoint* mp = sMountPointList;        while (mp)    {        // see if the device matches mount point's block device        if (mp->state == kUnmounted &&                strncmp(device, mp->device + DEVPATHLENGTH, strlen(mp->device) - DEVPATHLENGTH) == 0)         {            if (MassStorageEnabledForMountPoint(mp))            {                SetBackingStore(mp, true);                NotifyMediaState(mp->mountPoint, MEDIA_SHARED, false);            }            else                RequestMount(mp);        }          mp = mp->next;    }}// called when a new block device has been deletedstatic void HandleMediaRemoved(const char* device){        MountPoint* mp = sMountPointList;    while (mp)    {        if (strncmp(device, mp->device + DEVPATHLENGTH, strlen(mp->device) - DEVPATHLENGTH) == 0)        {            if (mp->enableUms)                SetBackingStore(mp, false);             if (mp->state == kMounted)             {                RequestUnmount(mp, kUnmountingForEject);                NotifyMediaState(mp->mountPoint, MEDIA_BAD_REMOVAL, false);            }                        NotifyMediaState(mp->mountPoint, MEDIA_REMOVED, false);            break;        }          mp = mp->next;    }}// Handle retrying to mount or unmount devices, // and handle timeout condition if we have tried too many timesstatic void HandleRetries(){    MountPoint* mp = sMountPointList;        while (mp)    {       if (mp->state == kMounting)        {            if (MountPartition(mp->device, mp->mountPoint) == 0)            {                // mount succeeded - clear the retry for this mount point                ClearRetries(mp, kMounted);            }             else             {                mp->retryCount++;                if (mp->retryCount == MAX_MOUNT_RETRIES)                {                    // we failed to mount the device too many times                    ClearRetries(mp, kUnmounted);                    // notify that we failed to mount                    NotifyMediaState(mp->mountPoint, MEDIA_UNMOUNTABLE, false);                }            }       }        else if (mp->state == kUnmountingForEject || mp->state == kUnmountingForUms)       {            if (DoUnmountDevice(mp->mountPoint) == 0)            {                // unmounting succeeded                // start mass storage, if state is kUnmountingForUms                if (mp->state == kUnmountingForUms)                {                    SetBackingStore(mp, true);                     NotifyMediaState(mp->mountPoint, MEDIA_SHARED, false);                }                // clear the retry for this mount point                ClearRetries(mp, kUnmounted);            }             else             {                mp->retryCount++;                if (mp->retryCount >= MAX_UNMOUNT_RETRIES)                {                    // kill any processes that are preventing the device from unmounting                    // send SIGKILL instead of SIGTERM if the first attempt did not succeed                    boolean sigkill = (mp->retryCount > MAX_UNMOUNT_RETRIES);                                        // unmounting the device is failing, so start killing processes                    KillProcessesWithOpenFiles(mp->mountPoint, sigkill);                }            }       }                 mp = mp->next;    }}/***************************************************** *  * AUTO-MOUNTER THREAD *  *****************************************************/static void sigusr1_handler(int signo){    // don't need to do anything here}// create a socket for listening to inotify eventsint CreateINotifySocket(){    // initialize inotify    int fd = inotify_init();    if (fd < 0) {        LOG_ERROR("inotify_init failed, %s\n", strerror(errno));        return -1;    }    fcntl(fd, F_SETFL, O_NONBLOCK | fcntl(fd, F_GETFL));    return fd;}// create a socket for listening to ueventsint CreateUEventSocket(){    struct sockaddr_nl addr;    int sz = 64*1024;    int fd;    memset(&addr, 0, sizeof(addr));    addr.nl_family = AF_NETLINK;    addr.nl_pid = getpid();    addr.nl_groups = 0xffffffff;   fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);    if(fd < 0)    {        LOG_ERROR("could not create NETLINK_KOBJECT_UEVENT socket\n");        return -1;    }    setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));    if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {        LOG_ERROR("could not bind NETLINK_KOBJECT_UEVENT socket\n");        close(fd);        return -1;    }    return fd;}/* * Automounter main event thread. * This thread listens for block devices being created and deleted via inotify, * and listens for changes in the USB mass storage connected/disconnected via uevents from the  * power supply driver. * This thread also handles retries and timeouts for requests to mount or unmount a device. */static void* AutoMountThread(void* arg){    int inotify_fd;    int uevent_fd;    int id;    struct sigaction    actions;    memset(&actions, 0, sizeof(actions));    sigemptyset(&actions.sa_mask);    actions.sa_flags = 0;    actions.sa_handler = sigusr1_handler;    sigaction(SIGUSR1, &actions, NULL);        // initialize inotify    inotify_fd = CreateINotifySocket();    // watch for files created and deleted in "/dev"    inotify_add_watch(inotify_fd, DEVPATH, IN_CREATE|IN_DELETE);    // initialize uevent watcher    uevent_fd = CreateUEventSocket();    if (uevent_fd < 0)     {        LOG_ERROR("CreateUEventSocket failed, %s\n", strerror(errno));        return NULL;    }        while (1)    {        struct pollfd fds[2];        int timeout, result;#define INOTIFY_IDX 0#define UEVENT_IDX  1            fds[INOTIFY_IDX].fd = inotify_fd;        fds[INOTIFY_IDX].events = POLLIN;        fds[INOTIFY_IDX].revents = 0;        fds[UEVENT_IDX].fd = uevent_fd;        fds[UEVENT_IDX].events = POLLIN;        fds[UEVENT_IDX].revents = 0;                // wait for an event or a timeout to occur.        // poll() can also return in response to a SIGUSR1 signal        timeout = (sRetriesPending ? POLL_TIMEOUT : -1);        result = poll(fds, 2, timeout);        // lock the mutex while we are handling events        pthread_mutex_lock(&sMutex);        // handle inotify notifications for block device creation and deletion        if (fds[INOTIFY_IDX].revents == POLLIN)        {            struct inotify_event    event;            char    buffer[512];            int length = read(inotify_fd, buffer, sizeof(buffer));            int offset = 0;             while (length >= (int)sizeof(struct inotify_event))            {               struct inotify_event* event = (struct inotify_event *)&buffer[offset];                              if (event->mask == IN_CREATE)               {                   LOG_MOUNT("/dev/block/%s created\n", event->name);                   HandleMediaInserted(event->name);               }               else if (event->mask == IN_DELETE)               {                   LOG_MOUNT("/dev/block/%s deleted\n", event->name);                   HandleMediaRemoved(event->name);               }                              int size = sizeof(struct inotify_event) + event->len;               length -= size;               offset += size;            }        }        // handle uevent notifications for USB state changes        if (fds[UEVENT_IDX].revents == POLLIN)        {            char buffer[64*1024];            int count;                        count = recv(uevent_fd, buffer, sizeof(buffer), 0);            if (count > 0) {                char* s = buffer;                char* end = s + count;                char* type = NULL;                char* online = NULL;                char* switchName = NULL;                char* switchState = NULL;                                                while (s < end) {                    if (!strncmp("POWER_SUPPLY_TYPE=", s, strlen("POWER_SUPPLY_TYPE=")))                        type = s + strlen("POWER_SUPPLY_TYPE=");                    else if (!strncmp("POWER_SUPPLY_ONLINE=", s, strlen("POWER_SUPPLY_ONLINE=")))                        online = s + strlen("POWER_SUPPLY_ONLINE=");                                        else if (!strncmp("SWITCH_NAME=", s, strlen("SWITCH_NAME=")))                        switchName = s + strlen("SWITCH_NAME=");                                        else if (!strncmp("SWITCH_STATE=", s, strlen("SWITCH_STATE=")))                        switchState = s + strlen("SWITCH_STATE=");                                        s += (strlen(s) + 1);                }                // we use the usb_mass_storage switch state to tell us when USB is online                if (switchName && switchState &&                         !strcmp(switchName, "usb_mass_storage") && !strcmp(switchState, "online"))                {                    LOG_MOUNT("USB online\n");                    HandleMassStorageOnline(true);                }                                // and we use the power supply state to tell us when USB is offline                // we can't rely on the switch for offline detection because we get false positives                // when USB is reenumerated by the host.                if (type && online && !strcmp(type, "USB") && !strcmp(online, "0"))                {                    LOG_MOUNT("USB offline\n");                    HandleMassStorageOnline(false);                }            }        }       // handle retries       if (sRetriesPending)            HandleRetries();        // done handling events, so unlock the mutex        pthread_mutex_unlock(&sMutex);    }    inotify_rm_watch(inotify_fd, id);    close(inotify_fd);    close(uevent_fd);    return NULL;}/***************************************************** *  * THESE FUNCTIONS ARE CALLED FROM THE SERVER THREAD *  *****************************************************/// Called to enable or disable USB mass storage supportvoid EnableMassStorage(boolean enable){    pthread_mutex_lock(&sMutex);    LOG_MOUNT("EnableMassStorage %s\n", (enable ? "true" : "false"));    gMassStorageEnabled = enable;    MassStorageStateChanged();    pthread_mutex_unlock(&sMutex); }// Called to request that the specified mount point be mountedvoid MountMedia(const char* mountPoint){    MountPoint* mp = sMountPointList;        pthread_mutex_lock(&sMutex);    while (mp)    {        if (strcmp(mp->mountPoint, mountPoint) == 0)        {            if (mp->state == kUnmountingForEject)            {                // handle the case where we try to remount before we actually unmounted                ClearRetries(mp, kMounted);            }                        // don't attempt to mount if mass storage is active            if (!MassStorageEnabledForMountPoint(mp))                RequestMount(mp);        }                mp = mp->next;    }    pthread_mutex_unlock(&sMutex); }// Called to request that the specified mount point be unmountedvoid UnmountMedia(const char* mountPoint){    MountPoint* mp = sMountPointList;        pthread_mutex_lock(&sMutex);    while (mp)    {        if (strcmp(mp->mountPoint, mountPoint) == 0)            RequestUnmount(mp, kUnmountingForEject);                mp = mp->next;    }    pthread_mutex_unlock(&sMutex);}boolean IsMassStorageEnabled(){    return gMassStorageEnabled;}boolean IsMassStorageConnected(){    return gMassStorageConnected;}/*********************************************** *  * THESE FUNCTIONS ARE CALLED ONLY AT STARTUP *  ***********************************************/ void AddMountPoint(const char* device, const char* mountPoint, boolean enableUms){    MountPoint* newMountPoint;        LOG_MOUNT("AddMountPoint device: %s, mountPoint: %s\n", device, mountPoint);    // add a new MountPoint to the head of our linked list    newMountPoint = (MountPoint *)malloc(sizeof(MountPoint));    newMountPoint->device = device;    newMountPoint->mountPoint = mountPoint;    newMountPoint->enableUms = enableUms;    newMountPoint->umsActive = false;    if (enableUms)        newMountPoint->lun = sNextLun++;    newMountPoint->state = kUnmounted;    newMountPoint->retryCount = 0;    // add to linked list    newMountPoint->next = sMountPointList;    sMountPointList = newMountPoint;}static void MountDevices(){    MountPoint* mp = sMountPointList;    while (mp)    {        RequestMount(mp);        mp = mp->next;    }}void StartAutoMounter(){    gMassStorageConnected = ReadMassStorageState();    LOG_MOUNT(gMassStorageConnected ? "USB online\n" : "USB offline\n");    MountDevices();    pthread_create(&sAutoMountThread, NULL, AutoMountThread, NULL);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -