FFmpeg
Loading...
Searching...
No Matches
ffplay_dir.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include "config.h"
20
21#include <errno.h>
22#include <limits.h>
23#include <stdlib.h>
24#include <string.h>
25#if HAVE_LSTAT
26#include <sys/stat.h>
27#endif
28
29#include "libavformat/avio.h"
30#include "libavutil/avstring.h"
31#include "libavutil/dict.h"
32#include "libavutil/dynarray.h"
33#include "libavutil/error.h"
34#include "libavutil/mem.h"
35
36#include "ffplay_dir.h"
37
43
44/* the directories first, then the entries that may be directories, then the files, each by name; the kind of an entry
45 * is kept in its length until the entries are sorted */
46static int compare_entries(const void *a, const void *b)
47{
48 const ListEntry *ea = a, *eb = b;
49 int kind = (eb->length > ea->length) - (eb->length < ea->length);
50 int cmp = av_strcasecmp(ea->title, eb->title);
51
52 return kind ? kind : cmp ? cmp : strcmp(ea->title, eb->title);
53}
54
55/* adds the entry, titled with a trailing slash when it is a directory and with its size when that is not negative */
56static int add_entry(DirList *dl, const char *name, enum EntryKind kind, int64_t size)
57{
59
60 FF_DYNARRAY_ADD(INT_MAX, sizeof(*entry), dl->entries, dl->nb_entries, {
61 entry = &dl->entries[dl->nb_entries];
62 }, {
63 return AVERROR(ENOMEM);
64 });
65 *entry = (ListEntry){ av_asprintf("%s%s", name, kind == ENTRY_DIR ? "/" : ""), NULL, kind, NULL };
66 if (!entry->title || (size >= 0 && av_dict_set_int(&entry->metadata, "size", size, 0) < 0))
67 return AVERROR(ENOMEM);
68 return 0;
69}
70
71/* whether the entry is listed, which hidden entries, special files and links to them are not; a link in a local
72 * directory is listed as what it points to, with its size */
73static int listed(const char *local_dir, AVIODirEntry *dirent)
74{
75 if (!dirent->name || !*dirent->name || dirent->name[0] == '.')
76 return 0;
77#if HAVE_LSTAT
78 if (dirent->type == AVIO_ENTRY_SYMBOLIC_LINK && local_dir) {
79 char *path = av_append_path_component(local_dir, dirent->name);
80 struct stat st;
81 int found;
82
83 if (!path)
84 return AVERROR(ENOMEM);
85 found = !stat(path, &st);
87 if (!found || !(S_ISDIR(st.st_mode) || S_ISREG(st.st_mode)))
88 return 0;
89 dirent->type = S_ISDIR(st.st_mode) ? AVIO_ENTRY_DIRECTORY : AVIO_ENTRY_FILE;
90 dirent->size = st.st_size;
91 }
92#endif
93 return dirent->type != AVIO_ENTRY_NAMED_PIPE && dirent->type != AVIO_ENTRY_CHARACTER_DEVICE &&
94 dirent->type != AVIO_ENTRY_BLOCK_DEVICE && dirent->type != AVIO_ENTRY_SOCKET;
95}
96
97/* the local directory as an absolute path without links, NULL with errno set when it cannot be resolved */
98static char *resolve_local(const char *path)
99{
100#if HAVE_REALPATH
101 char *resolved = realpath(path, NULL), *copy = resolved ? av_strdup(resolved) : NULL;
102
103 if (resolved && !copy)
104 errno = ENOMEM;
105 free(resolved);
106 return copy;
107#else
108 errno = ENOSYS;
109 return NULL;
110#endif
111}
112
114{
115 const char *protocol = avio_find_protocol_name(path);
116 int local = !protocol || !strcmp(protocol, "file");
118 AVIODirEntry *dirent = NULL;
119 DirList *dl = av_mallocz(sizeof(*dl));
120 int ret;
121
122 if (!dl)
123 return AVERROR(ENOMEM);
124 if (local)
125 av_strstart(path, "file:", &path);
126 dl->path = local ? resolve_local(path) : av_strdup(path);
127 if (!dl->path) {
128 ret = AVERROR(local ? errno : ENOMEM);
129 goto fail;
130 }
131 if ((ret = add_entry(dl, "..", ENTRY_DIR, -1)) < 0 || (ret = avio_open_dir2(&ctx, dl->path, int_cb, options)) < 0)
132 goto fail;
133 while ((ret = avio_read_dir(ctx, &dirent)) >= 0 && dirent) {
134 if (int_cb && int_cb->callback && int_cb->callback(int_cb->opaque))
136 else if ((ret = listed(local ? dl->path : NULL, dirent)) > 0)
137 ret = add_entry(dl, dirent->name, dirent->type == AVIO_ENTRY_DIRECTORY ? ENTRY_DIR :
138 dirent->type == AVIO_ENTRY_FILE ? ENTRY_FILE : ENTRY_MAYBE_DIR, dirent->size);
140 if (ret < 0)
141 break;
142 }
144 if (ret < 0)
145 goto fail;
146 qsort(dl->entries + 1, dl->nb_entries - 1, sizeof(*dl->entries), compare_entries);
147 for (int i = 0; i < dl->nb_entries; i++) {
148 dl->nb_dirs += dl->entries[i].length == ENTRY_DIR;
149 dl->nb_maybe_dirs += dl->entries[i].length == ENTRY_MAYBE_DIR;
150 dl->entries[i].length = -1;
151 }
152 *pdl = dl;
153 return 0;
154fail:
156 return ret;
157}
158
160{
161 DirList *dl = *pdl;
162
163 if (!dl)
164 return;
165 for (int i = 0; i < dl->nb_entries; i++) {
166 av_freep(&dl->entries[i].title);
167 av_dict_free(&dl->entries[i].metadata);
168 }
169 av_freep(&dl->entries);
170 av_freep(&dl->path);
171 av_freep(pdl);
172}
173
174/* the directory above, which is the root of a path or the host of a URL at most */
175static char *parent_path(const char *path)
176{
177 const char *scheme = *path == '/' ? NULL : strstr(path, "://");
178 const char *top = scheme ? strchr(scheme + 3, '/') : path;
179 const char *slash = top ? strrchr(top, '/') : NULL;
180
181 return av_strndup(path, slash ? FFMAX(slash, top + !scheme) - path : strlen(path));
182}
183
184char *dir_list_path(const DirList *dl, int entry)
185{
186 const char *title = dl->entries[entry].title;
187 char *path;
188
189 if (!entry)
190 return parent_path(dl->path);
191 path = av_append_path_component(dl->path, title);
192 if (path && entry < dl->nb_dirs)
193 path[strlen(path) - 1] = 0;
194 return path;
195}
#define entry
static AVFormatContext * ctx
int avio_open_dir2(AVIODirContext **s, const char *url, const AVIOInterruptCB *int_cb, AVDictionary **options)
Open directory for reading, with an interrupt callback for the protocol.
Definition avio.c:800
int avio_close_dir(AVIODirContext **s)
Close directory.
Definition avio.c:856
void avio_free_directory_entry(AVIODirEntry **entry)
Free entry allocated by avio_read_dir().
Definition avio.c:871
int avio_read_dir(AVIODirContext *s, AVIODirEntry **next)
Get next directory entry.
Definition avio.c:843
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition avio.c:732
Buffered I/O operations.
@ AVIO_ENTRY_NAMED_PIPE
Definition avio.h:72
@ AVIO_ENTRY_BLOCK_DEVICE
Definition avio.h:69
@ AVIO_ENTRY_SYMBOLIC_LINK
Definition avio.h:73
@ AVIO_ENTRY_DIRECTORY
Definition avio.h:71
@ AVIO_ENTRY_CHARACTER_DEVICE
Definition avio.h:70
@ AVIO_ENTRY_FILE
Definition avio.h:75
@ AVIO_ENTRY_SOCKET
Definition avio.h:74
char * av_asprintf(const char *fmt,...)
Definition avstring.c:115
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
Public dictionary API.
#define FF_DYNARRAY_ADD(av_size_max, av_elt_size, av_array, av_size, av_success, av_failure)
Add an element to a dynamic array.
Definition dynarray.h:45
error code definitions
const AVIOInterruptCB int_cb
Definition ffmpeg.c:322
char * path
Definition ffplay.c:385
int ret
Definition ffplay.c:391
DirList * dl
Definition ffplay.c:390
static int add_entry(DirList *dl, const char *name, enum EntryKind kind, int64_t size)
Definition ffplay_dir.c:56
static char * resolve_local(const char *path)
Definition ffplay_dir.c:98
static int compare_entries(const void *a, const void *b)
Definition ffplay_dir.c:46
EntryKind
Definition ffplay_dir.c:38
@ ENTRY_DIR
Definition ffplay_dir.c:41
@ ENTRY_FILE
Definition ffplay_dir.c:39
@ ENTRY_MAYBE_DIR
Definition ffplay_dir.c:40
static char * parent_path(const char *path)
Definition ffplay_dir.c:175
static int listed(const char *local_dir, AVIODirEntry *dirent)
Definition ffplay_dir.c:73
int dir_list_read(DirList **pdl, const char *path, const AVIOInterruptCB *int_cb, AVDictionary **options)
Reads the directory into a new list.
Definition ffplay_dir.c:113
void dir_list_free(DirList **pdl)
Definition ffplay_dir.c:159
char * dir_list_path(const DirList *dl, int entry)
Definition ffplay_dir.c:184
The content of a directory as list entries, leaving out hidden entries, special files and links to th...
#define fail
Definition test.h:479
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:236
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
Definition dict.c:180
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition error.h:58
#define AVERROR(e)
Definition error.h:45
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition mem.c:390
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition avstring.c:208
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition avstring.c:36
char * av_append_path_component(const char *path, const char *component)
Append path component to the existing path.
Definition avstring.c:295
int a
#define b
Definition input.c:43
#define S_ISREG(m)
Definition file.c:80
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
static av_always_inline int cmp(MPVEncContext *const s, const int x, const int y, const int subx, const int suby, const int size, const int h, int ref_index, int src_index, me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags)
compares a block (either a full macroblock or a partition thereof) against a proposed motion-compensa...
Definition motion_est.c:263
#define av_strdup(s)
Definition ops_static.c:55
const char * name
Definition qsvenc.c:142
Describes single entry of the directory.
Definition avio.h:87
int type
Type of the entry.
Definition avio.h:89
int64_t size
File size in bytes, -1 if unknown.
Definition avio.h:92
char * name
Filename.
Definition avio.h:88
Callback for checking whether to abort blocking functions.
Definition avio.h:59
const char * title
Definition ffplay_list.h:37
int64_t length
in AV_TIME_BASE units, negative when unknown
Definition ffplay_list.h:39
#define av_free(p)
#define av_mallocz(s)
#define av_freep(p)
int size
static void copy(const float *p1, float *p2, const int length)