예제 #1
0
파일: filetree.c 프로젝트: jdgordon/rockbox
/* walk a directory and check all entries if a .talk file exists */
static void check_file_thumbnails(struct tree_context* c)
{
    int i;
    struct dirent *entry;
    struct entry* entries;
    DIR *dir;

    dir = opendir(c->currdir);
    if(!dir)
        return;
    /* mark all files as non talking, except the .talk ones */
    entries = tree_get_entries(c);
    tree_lock_cache(c);
    for (i=0; i < c->filesindir; i++)
    {
        if (entries[i].attr & ATTR_DIRECTORY)
            continue; /* we're not touching directories */

        if (strcasecmp(file_thumbnail_ext,
            &entries[i].name[strlen(entries[i].name)
                              - strlen(file_thumbnail_ext)]))
        {   /* no .talk file */
            entries[i].attr &= ~FILE_ATTR_THUMBNAIL; /* clear */
        }
        else
        {   /* .talk file, we later let them speak themselves */
            entries[i].attr |= FILE_ATTR_THUMBNAIL; /* set */
        }
    }

    while((entry = readdir(dir)) != 0) /* walk directory */
    {
        int ext_pos;
        struct dirinfo info = dir_get_info(dir, entry);
        ext_pos = strlen((char *)entry->d_name) - strlen(file_thumbnail_ext);
        if (ext_pos <= 0 /* too short to carry ".talk" */
            || (info.attribute & ATTR_DIRECTORY) /* no file */
            || strcasecmp((char *)&entry->d_name[ext_pos], file_thumbnail_ext))
        {   /* or doesn't end with ".talk", no candidate */
            continue;
        }

        /* terminate the (disposable) name in dir buffer,
           this truncates off the ".talk" without needing an extra buffer */
        entry->d_name[ext_pos] = '\0';

        /* search corresponding file in dir cache */
        for (i=0; i < c->filesindir; i++)
        {
            if (!strcasecmp(entries[i].name, (char *)entry->d_name))
            {   /* match */
                entries[i].attr |= FILE_ATTR_THUMBNAIL; /* set the flag */
                break; /* exit search loop, because we found it */
            }
        }
    }
    tree_unlock_cache(c);
    closedir(dir);
}
예제 #2
0
/* helper function to remove a non-empty directory */
static int remove_dir(char* dirname, int len)
{
    int result = 0;
    DIR* dir;
    int dirlen = strlen(dirname);

    dir = opendir(dirname);
    if (!dir)
        return -1; /* open error */

    while(true)
    {
        struct dirent* entry;
        /* walk through the directory content */
        entry = readdir(dir);
        if (!entry)
            break;
        struct dirinfo info = dir_get_info(dir, entry);
        dirname[dirlen] ='\0';
        /* inform the user which dir we're deleting */
        splash(0, dirname);

        /* append name to current directory */
        snprintf(dirname+dirlen, len-dirlen, "/%s", entry->d_name);
        if (info.attribute & ATTR_DIRECTORY)
        {   /* remove a subdirectory */
            if (!strcmp((char *)entry->d_name, ".") ||
                !strcmp((char *)entry->d_name, ".."))
                continue; /* skip these */

            result = remove_dir(dirname, len); /* recursion */
            if (result)
                break; /* or better continue, delete what we can? */
        }
        else
        {   /* remove a file */
            draw_slider();
            result = remove(dirname);
        }
        if(ACTION_STD_CANCEL == get_action(CONTEXT_STD,TIMEOUT_NOBLOCK))
        {
            splash(HZ, ID2P(LANG_CANCEL));
            result = -1;
            break;
        }
    }
    closedir(dir);

    if (!result)
    {   /* remove the now empty directory */
        dirname[dirlen] = '\0'; /* terminate to original length */

        result = rmdir(dirname);
    }

    return result;
}
예제 #3
0
/* Paste a directory to a new location. Designed to be called by
   clipboard_paste */
static bool clipboard_pastedirectory(char *src, int srclen, char *target,
                                     int targetlen, bool copy)
{
    DIR *srcdir;
    int srcdirlen = strlen(src);
    int targetdirlen = strlen(target);
    bool result = true;

    if (!file_exists(target)) {
        if (!copy) {
            /* Just move the directory */
            result = rename(src, target) == 0;

#ifdef HAVE_MULTIVOLUME
            if (!result && errno == EXDEV) {
                /* Try a copy as we're going across devices */
                result = clipboard_pastedirectory(src, srclen, target,
                    targetlen, true);

                /* If it worked, remove the source directory */
                if (result) {
                    remove_dir(src, srclen);
                }
            }
#endif
            return result;
        } else {
            /* Make a directory to copy things to */
            result = mkdir(target) == 0;
        }
    }

    /* Check if something went wrong already */
    if (!result) {
        return result;
    }

    srcdir = opendir(src);
    if (!srcdir) {
        return false;
    }

    /* This loop will exit as soon as there's a problem */
    while(result)
    {
        struct dirent* entry;
        /* walk through the directory content */
        entry = readdir(srcdir);
        if (!entry)
            break;

        struct dirinfo info = dir_get_info(srcdir, entry);
        /* append name to current directory */
        snprintf(src+srcdirlen, srclen-srcdirlen, "/%s", entry->d_name);
        snprintf(target+targetdirlen, targetlen-targetdirlen, "/%s",
            entry->d_name);

        DEBUGF("Copy %s to %s\n", src, target);

        if (info.attribute & ATTR_DIRECTORY)
        {   /* copy/move a subdirectory */
            if (!strcmp((char *)entry->d_name, ".") ||
                !strcmp((char *)entry->d_name, ".."))
                continue; /* skip these */

            result = clipboard_pastedirectory(src, srclen, target, targetlen,
                copy); /* recursion */
        }
        else
        {   /* copy/move a file */
            draw_slider();
            result = clipboard_pastefile(src, target, copy);
        }
    }

    closedir(srcdir);

    if (result) {
        src[srcdirlen] = '\0'; /* terminate to original length */
        target[targetdirlen] = '\0'; /* terminate to original length */
    }

    return result;
}
예제 #4
0
파일: filetree.c 프로젝트: skeller/rockbox
/* load and sort directory into the tree's cache. returns NULL on failure. */
int ft_load(struct tree_context* c, const char* tempdir)
{
    int files_in_dir = 0;
    int name_buffer_used = 0;
    struct dirent *entry;
    bool (*callback_show_item)(char *, int, struct tree_context *) = NULL;
    DIR *dir;

    if (tempdir)
        dir = opendir(tempdir);
    else
    {
        dir = opendir(c->currdir);
        callback_show_item = c->browse? c->browse->callback_show_item: NULL;
    }
    if(!dir)
        return -1; /* not a directory */

    c->dirsindir = 0;
    c->dirfull = false;

    while ((entry = readdir(dir))) {
        int len;
        struct dirinfo info;
        struct entry* table = c->cache.entries;
        struct entry* dptr = &table[files_in_dir];
        if (!entry)
            break;

        info = dir_get_info(dir, entry);
        len = strlen((char *)entry->d_name);

        /* skip directories . and .. */
        if ((info.attribute & ATTR_DIRECTORY) &&
            (((len == 1) && (!strncmp((char *)entry->d_name, ".", 1))) ||
             ((len == 2) && (!strncmp((char *)entry->d_name, "..", 2))))) {
            continue;
        }

        /* Skip FAT volume ID */
        if (info.attribute & ATTR_VOLUME_ID) {
            continue;
        }

        /* filter out dotfiles and hidden files */
        if (*c->dirfilter != SHOW_ALL &&
            ((entry->d_name[0]=='.') ||
            (info.attribute & ATTR_HIDDEN))) {
            continue;
        }

        dptr->attr = info.attribute;

        /* check for known file types */
        if ( !(dptr->attr & ATTR_DIRECTORY) )
            dptr->attr |= filetype_get_attr((char *)entry->d_name);

        /* filter out non-visible files */
        if ((!(dptr->attr & ATTR_DIRECTORY) && (
            (*c->dirfilter == SHOW_PLAYLIST &&
             (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) ||
            ((*c->dirfilter == SHOW_MUSIC &&
             (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) &&
             (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) ||
            (*c->dirfilter == SHOW_SUPPORTED && !filetype_supported(dptr->attr)))) ||
            (*c->dirfilter == SHOW_WPS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_WPS) ||
#ifdef HAVE_LCD_BITMAP
            (*c->dirfilter == SHOW_FONT && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_FONT) ||
            (*c->dirfilter == SHOW_SBS  && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_SBS) ||
#if CONFIG_TUNER
            (*c->dirfilter == SHOW_FMS  && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_FMS) ||
#endif
#endif
#ifdef HAVE_REMOTE_LCD
            (*c->dirfilter == SHOW_RWPS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_RWPS) ||
            (*c->dirfilter == SHOW_RSBS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_RSBS) ||
#if CONFIG_TUNER
            (*c->dirfilter == SHOW_RFMS  && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_RFMS) ||
#endif
#endif
#if CONFIG_TUNER
            (*c->dirfilter == SHOW_FMR && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_FMR) ||
#endif
            (*c->dirfilter == SHOW_M3U && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) ||
            (*c->dirfilter == SHOW_CFG && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_CFG) ||
            (*c->dirfilter == SHOW_LNG && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LNG) ||
            (*c->dirfilter == SHOW_MOD && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_MOD) ||
            (*c->dirfilter == SHOW_PLUGINS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_ROCK &&
                                              (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LUA) ||
            (callback_show_item && !callback_show_item(entry->d_name, dptr->attr, c)))
        {
            continue;
        }

        if ((len > c->cache.name_buffer_size - name_buffer_used - 1) ||
            (files_in_dir >= c->cache.max_entries)) {
            /* Tell the world that we ran out of buffer space */
            c->dirfull = true;
            break;
        }

        ++files_in_dir;

        dptr->name = &c->cache.name_buffer[name_buffer_used];
        dptr->time_write =
            (long)info.wrtdate<<16 |
            (long)info.wrttime; /* in one # */
        strcpy(dptr->name, (char *)entry->d_name);
        name_buffer_used += len + 1;

        if (dptr->attr & ATTR_DIRECTORY) /* count the remaining dirs */
            c->dirsindir++;
    }
    c->filesindir = files_in_dir;
    c->dirlength = files_in_dir;
    closedir(dir);

    compare_sort_dir = c->sort_dir;
    qsort(c->cache.entries, files_in_dir, sizeof(struct entry), compare);

    /* If thumbnail talking is enabled, make an extra run to mark files with
       associated thumbnails, so we don't do unsuccessful spinups later. */
    if (global_settings.talk_file_clip)
        check_file_thumbnails(c); /* map .talk to ours */

    return 0;
}
예제 #5
0
static struct folder* load_folder(struct folder* parent, char *folder)
{
    DIR *dir;
    char* path = get_full_path(parent);
    char fullpath[MAX_PATH];
    struct dirent *entry;
    struct folder* this = (struct folder*)folder_alloc(sizeof(struct folder));
    int child_count = 0;
    char *first_child = NULL;

    if (!strcmp(folder,"/"))
        strlcpy(fullpath, folder, 2);
    else
        snprintf(fullpath, MAX_PATH, "%s/%s", parent ? path : "", folder);

    if (!this)
        return NULL;
    dir = opendir(fullpath);
    if (!dir)
        return NULL;
    this->previous = parent;
    this->name = folder;
    this->children = NULL;
    this->children_count = 0;
    this->depth = parent ? parent->depth + 1 : 0;

    while ((entry = readdir(dir))) {
        int len = strlen((char *)entry->d_name);
        struct dirinfo info;

        info = dir_get_info(dir, entry);

        /* skip anything not a directory */
        if ((info.attribute & ATTR_DIRECTORY) == 0) {
            continue;
        }
        /* skip directories . and .. */
        if ((!strcmp((char *)entry->d_name, ".")) ||
            (!strcmp((char *)entry->d_name, ".."))) {
            continue;
        }
        char *name = folder_alloc_from_end(len+1);
        if (!name)
            return NULL;
        memcpy(name, (char *)entry->d_name, len+1);
        child_count++;
        first_child = name;
    }
    closedir(dir);
    /* now put the names in the array */
    this->children = (struct child*)folder_alloc(sizeof(struct child) * child_count);

    if (!this->children)
        return NULL;
    while (child_count)
    {
        this->children[this->children_count].name = first_child;
        this->children[this->children_count].folder = NULL;
        this->children[this->children_count].state = COLLAPSED;
        this->children_count++;
        first_child += strlen(first_child) + 1;
        child_count--;
    }
    qsort(this->children, this->children_count, sizeof(struct child), compare);

    return this;
}