summaryrefslogtreecommitdiff
path: root/src/input/input_file.c
diff options
context:
space:
mode:
authorDaniel Caujolle-Bert <f1rmb@users.sourceforge.net>2001-07-10 21:07:55 +0000
committerDaniel Caujolle-Bert <f1rmb@users.sourceforge.net>2001-07-10 21:07:55 +0000
commit4cc9fd313df701f722a81ad4bb551155415ce5cc (patch)
treecafd04a6191675accbc2d168192eee7169a6056b /src/input/input_file.c
parent9125c00c6d1242b911cbf68cdd25114cd9972c8f (diff)
downloadxine-lib-4cc9fd313df701f722a81ad4bb551155415ce5cc.tar.gz
xine-lib-4cc9fd313df701f722a81ad4bb551155415ce5cc.tar.bz2
Fixed get_dir in input plugins. Fixed a strange header inclusion bug
in libw32dll/wine. CVS patchset: 264 CVS date: 2001/07/10 21:07:55
Diffstat (limited to 'src/input/input_file.c')
-rw-r--r--src/input/input_file.c506
1 files changed, 405 insertions, 101 deletions
diff --git a/src/input/input_file.c b/src/input/input_file.c
index 6a6bbfba9..182c34d5f 100644
--- a/src/input/input_file.c
+++ b/src/input/input_file.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: input_file.c,v 1.15 2001/07/01 23:37:04 guenter Exp $
+ * $Id: input_file.c,v 1.16 2001/07/10 21:07:55 f1rmb Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -43,6 +43,8 @@ extern int errno;
static uint32_t xine_debug;
+#define MAXFILES 65535
+
#ifndef S_ISLNK
#define S_ISLNK(mode) 0
#endif
@@ -77,6 +79,151 @@ typedef struct {
} file_input_plugin_t;
+
+/* ***************************************************************************
+ * PRIVATES FUNCTIONS
+ */
+
+/*
+ * Sorting function, it comes from GNU fileutils package.
+ */
+#define S_N 0x0
+#define S_I 0x4
+#define S_F 0x8
+#define S_Z 0xC
+#define CMP 2
+#define LEN 3
+#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
+static int strverscmp(const char *s1, const char *s2) {
+ const unsigned char *p1 = (const unsigned char *) s1;
+ const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+ int state;
+ int diff;
+ static const unsigned int next_state[] = {
+ S_N, S_I, S_Z, S_N,
+ S_N, S_I, S_I, S_I,
+ S_N, S_F, S_F, S_F,
+ S_N, S_F, S_Z, S_Z
+ };
+ static const int result_type[] = {
+ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ CMP, -1, -1, CMP, 1, LEN, LEN, CMP,
+ 1, LEN, LEN, CMP, CMP, CMP, CMP, CMP,
+ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ CMP, 1, 1, CMP, -1, CMP, CMP, CMP,
+ -1, CMP, CMP, CMP
+ };
+
+ if(p1 == p2)
+ return 0;
+
+ c1 = *p1++;
+ c2 = *p2++;
+
+ state = S_N | ((c1 == '0') + (ISDIGIT(c1) != 0));
+
+ while((diff = c1 - c2) == 0 && c1 != '\0') {
+ state = next_state[state];
+ c1 = *p1++;
+ c2 = *p2++;
+ state |= (c1 == '0') + (ISDIGIT(c1) != 0);
+ }
+
+ state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT(c2) != 0))];
+
+ switch(state) {
+ case CMP:
+ return diff;
+
+ case LEN:
+ while(ISDIGIT(*p1++))
+ if(!ISDIGIT(*p2++))
+ return 1;
+
+ return ISDIGIT(*p2) ? -1 : diff;
+
+ default:
+ return state;
+ }
+}
+
+/*
+ * Wrapper to strverscmp() for qsort() calls, which sort mrl_t type array.
+ */
+static int _sortfiles_default(const mrl_t *s1, const mrl_t *s2) {
+ return(strverscmp(s1->mrl, s2->mrl));
+}
+
+/*
+ * Return the type (OR'ed) of the given file *fully named*
+ */
+static uint32_t get_file_type(char *filepathname, char *origin) {
+ struct stat pstat;
+ int mode;
+ uint32_t file_type = 0;
+ char buf[PATH_MAX + NAME_MAX + 1];
+
+ if((lstat(filepathname, &pstat)) < 0) {
+ sprintf(buf, "%s/%s", origin, filepathname);
+ if((lstat(buf, &pstat)) < 0) {
+ printf("lstat failed for %s{%s}\n", filepathname, origin);
+ file_type |= mrl_unknown;
+ return file_type;
+ }
+ }
+
+ file_type |= mrl_file;
+
+ mode = pstat.st_mode;
+
+ if(S_ISLNK(mode))
+ file_type |= mrl_file_symlink;
+ else if(S_ISDIR(mode))
+ file_type |= mrl_file_directory;
+ else if(S_ISCHR(mode))
+ file_type |= mrl_file_chardev;
+ else if(S_ISBLK(mode))
+ file_type |= mrl_file_blockdev;
+ else if(S_ISFIFO(mode))
+ file_type |= mrl_file_fifo;
+ else if(S_ISSOCK(mode))
+ file_type |= mrl_file_sock;
+ else {
+ if(S_ISREG(mode)) {
+ file_type |= mrl_file_normal;
+ }
+ if(mode & S_IXUGO)
+ file_type |= mrl_file_exec;
+ }
+
+ if(filepathname[strlen(filepathname) - 1] == '~')
+ file_type |= mrl_file_backup;
+
+ return file_type;
+}
+
+/*
+ * Return the file size of the given file *fully named*
+ */
+static off_t get_file_size(char *filepathname, char *origin) {
+ struct stat pstat;
+ char buf[PATH_MAX + NAME_MAX + 1];
+
+ if((lstat(filepathname, &pstat)) < 0) {
+ sprintf(buf, "%s/%s", origin, filepathname);
+ if((lstat(buf, &pstat)) < 0)
+ return (off_t) 0;
+ }
+
+ return pstat.st_size;
+}
+/*
+ * END OF PRIVATES
+ *****************************************************************************/
+
/*
*
*/
@@ -186,18 +333,33 @@ static uint32_t file_plugin_get_blocksize (input_plugin_t *this_gen) {
}
/*
+ * Return 1 is filepathname is a directory, otherwise 0
+ */
+static int is_a_dir(char *filepathname) {
+ struct stat pstat;
+
+ stat(filepathname, &pstat);
+
+ return (S_ISDIR(pstat.st_mode));
+}
+
+/*
*
*/
static mrl_t **file_plugin_get_dir (input_plugin_t *this_gen,
char *filename, int *nFiles) {
file_input_plugin_t *this = (file_input_plugin_t *) this_gen;
- char current_dir[PATH_MAX + 1];
- char *fullpathname = NULL;
struct dirent *pdirent;
DIR *pdir;
- mode_t mode;
- struct stat pstat;
- int num_files = 0;
+ mrl_t *hide_files, *dir_files, *norm_files;
+ char current_dir[PATH_MAX + 1];
+ char current_dir_slashed[PATH_MAX + 1];
+ char fullfilename[PATH_MAX + NAME_MAX + 1];
+ int num_hide_files = 0;
+ int num_dir_files = 0;
+ int num_norm_files = 0;
+ int num_files = -1;
+ int (*func) () = _sortfiles_default;
*nFiles = 0;
memset(&current_dir, 0, strlen(current_dir));
@@ -213,126 +375,268 @@ static mrl_t **file_plugin_get_dir (input_plugin_t *this_gen,
else
snprintf(current_dir, PATH_MAX, "%s", pwd);
}
- else
+ else {
+
+ /* Remove exceed '/' */
+ while((filename[strlen(filename) - 1] == '/') && strlen(filename) > 1)
+ filename[strlen(filename) - 1] = '\0';
+
snprintf(current_dir, PATH_MAX, "%s", filename);
+ }
+
+ if(strcasecmp(current_dir, "/"))
+ sprintf(current_dir_slashed, "%s/", current_dir);
+ else
+ sprintf(current_dir_slashed, "/");
+
/*
* Ooch!
*/
- if((pdir = opendir(current_dir)) == NULL) {
- return NULL;
- }
-
+ if((pdir = opendir(current_dir)) == NULL)
+ return NULL;
+
+ dir_files = (mrl_t *) xmalloc(sizeof(mrl_t) * MAXFILES);
+ hide_files = (mrl_t *) xmalloc(sizeof(mrl_t) * MAXFILES);
+ norm_files = (mrl_t *) xmalloc(sizeof(mrl_t) * MAXFILES);
+
while((pdirent = readdir(pdir)) != NULL) {
- /*
- * full pathname creation
- */
- if(!fullpathname) {
- fullpathname = (char *)
- malloc((strlen(current_dir) + strlen(pdirent->d_name) + 2));
- }
- else {
- fullpathname = (char *)
- realloc(fullpathname,
- (strlen(current_dir) + strlen(pdirent->d_name) + 2));
- }
-
- sprintf(fullpathname, "%s/%s", current_dir, pdirent->d_name);
- /*
- * stat the file
- */
- if(lstat(fullpathname, &pstat) < 0) {
- fprintf(stderr, "lstat() failed: %s\n", strerror(errno));
- free(fullpathname);
- return NULL;
- }
+ memset(&fullfilename, 0, strlen(fullfilename));
+ sprintf(fullfilename, "%s/%s", current_dir, pdirent->d_name);
- /*
- * alloc enought memory in private plugin structure to
- * store found mrls.
- */
- if(num_files >= this->mrls_allocated_entries
- || this->mrls_allocated_entries == 0) {
-
- if((this->mrls[num_files] = (mrl_t *) malloc(sizeof(mrl_t))) == NULL) {
- fprintf(stderr, "malloc() failed: %s\n", strerror(errno));
- return NULL;
+ if(is_a_dir(fullfilename)) {
+
+ dir_files[num_dir_files].mrl = (char *)
+ xmalloc(strlen(current_dir_slashed) + 1 + strlen(pdirent->d_name) + 1);
+
+ dir_files[num_dir_files].origin = strdup(current_dir);
+ sprintf(dir_files[num_dir_files].mrl, "%s%s",
+ current_dir_slashed, pdirent->d_name);
+ dir_files[num_dir_files].link = NULL;
+ dir_files[num_dir_files].type = get_file_type(fullfilename, current_dir);
+ dir_files[num_dir_files].size = get_file_size(fullfilename, current_dir);
+
+ /* The file is a link, follow it */
+ if(dir_files[num_dir_files].type & mrl_file_symlink) {
+ char linkbuf[PATH_MAX + NAME_MAX + 1];
+ int linksize;
+
+ memset(&linkbuf, 0, PATH_MAX + NAME_MAX);
+ linksize = readlink(fullfilename, linkbuf, PATH_MAX + NAME_MAX);
+
+ if(linksize < 0) {
+ fprintf(stderr, "%s(%d): readlink() failed: %s\n",
+ __FUNCTION__, __LINE__, strerror(errno));
+ }
+ else {
+ dir_files[num_dir_files].link = (char *) xmalloc(linksize + 1);
+ strncpy(dir_files[num_dir_files].link, linkbuf, linksize);
+ dir_files[num_dir_files].type |= get_file_type(dir_files[num_dir_files].link, current_dir);
+ }
}
-
- this->mrls[num_files]->mrl = (char *) malloc(strlen(fullpathname) + 1);
-
- }
+
+ num_dir_files++;
+ } /* Hmmmm, an hidden file ? */
+ else if((strlen(pdirent->d_name) > 1)
+ && (pdirent->d_name[0] == '.' && pdirent->d_name[1] != '.')) {
+
+ hide_files[num_hide_files].mrl = (char *)
+ xmalloc(strlen(current_dir_slashed) + 1 + strlen(pdirent->d_name) + 1);
+
+ hide_files[num_hide_files].origin = strdup(current_dir);
+ sprintf(hide_files[num_hide_files].mrl, "%s%s",
+ current_dir_slashed, pdirent->d_name);
+ hide_files[num_hide_files].link = NULL;
+ hide_files[num_hide_files].type = get_file_type(fullfilename, current_dir);
+ hide_files[num_hide_files].size = get_file_size(fullfilename, current_dir);
+
+ /* The file is a link, follow it */
+ if(hide_files[num_hide_files].type & mrl_file_symlink) {
+ char linkbuf[PATH_MAX + NAME_MAX + 1];
+ int linksize;
+
+ memset(&linkbuf, 0, PATH_MAX + NAME_MAX);
+ linksize = readlink(fullfilename, linkbuf, PATH_MAX + NAME_MAX);
+
+ if(linksize < 0) {
+ fprintf(stderr, "%s(%d): readlink() failed: %s\n",
+ __FUNCTION__, __LINE__, strerror(errno));
+ }
+ else {
+ hide_files[num_hide_files].link = (char *)
+ xmalloc(linksize + 1);
+ strncpy(hide_files[num_hide_files].link, linkbuf, linksize);
+ hide_files[num_hide_files].type |= get_file_type(hide_files[num_hide_files].link, current_dir);
+ }
+ }
+
+ num_hide_files++;
+ } /* So a *normal* one. */
else {
- printf("realloc\n");
- this->mrls[num_files]->mrl = (char *)
- realloc(this->mrls[num_files]->mrl, strlen(fullpathname) + 1);
- }
-
- sprintf(this->mrls[num_files]->mrl, "%s", fullpathname);
-
- this->mrls[num_files]->size = pstat.st_size;
- /*
- * Ok, now check file type
- */
- mode = pstat.st_mode;
-
- if(S_ISLNK(mode)) {
- this->mrls[num_files]->type = mrl_symbolic_link;
- /*
- * So follow the link
- */
- {
- char *linkbuf;
+ norm_files[num_norm_files].mrl = (char *)
+ xmalloc(strlen(current_dir_slashed) + 1 + strlen(pdirent->d_name) + 1);
+
+ norm_files[num_norm_files].origin = strdup(current_dir);
+ sprintf(norm_files[num_norm_files].mrl, "%s%s",
+ current_dir_slashed, pdirent->d_name);
+ norm_files[num_norm_files].link = NULL;
+ norm_files[num_norm_files].type = get_file_type(fullfilename, current_dir);
+ norm_files[num_norm_files].size = get_file_size(fullfilename, current_dir);
+
+ /* The file is a link, follow it */
+ if(norm_files[num_norm_files].type & mrl_file_symlink) {
+ char linkbuf[PATH_MAX + NAME_MAX + 1];
int linksize;
- linkbuf = (char *) alloca(PATH_MAX + 2);
- memset(linkbuf, 0, sizeof(linkbuf));
- linksize = readlink(fullpathname, linkbuf, PATH_MAX + 1);
+ memset(&linkbuf, 0, PATH_MAX + NAME_MAX);
+ linksize = readlink(fullfilename, linkbuf, PATH_MAX + NAME_MAX);
if(linksize < 0) {
- fprintf(stderr, "readlink() failed: %s\n", strerror(errno));
+ fprintf(stderr, "%s(%d): readlink() failed: %s\n",
+ __FUNCTION__, __LINE__, strerror(errno));
}
else {
- this->mrls[num_files]->mrl = (char *)
- realloc(this->mrls[num_files]->mrl, (linksize + 1));
- memset(this->mrls[num_files]->mrl, 0, linksize + 1);
- strncpy(this->mrls[num_files]->mrl, linkbuf, linksize);
+ norm_files[num_norm_files].link = (char *)
+ xmalloc(linksize + 1);
+ strncpy(norm_files[num_norm_files].link, linkbuf, linksize);
+ norm_files[num_norm_files].type |= get_file_type(norm_files[num_norm_files].link, current_dir);
}
}
+
+ num_norm_files++;
}
- else if(S_ISDIR(mode))
- this->mrls[num_files]->type = mrl_directory;
- else if(S_ISCHR(mode))
- this->mrls[num_files]->type = mrl_chardev;
- else if(S_ISBLK(mode))
- this->mrls[num_files]->type = mrl_blockdev;
- else if(S_ISFIFO(mode))
- this->mrls[num_files]->type = mrl_fifo;
- else if(S_ISSOCK(mode))
- this->mrls[num_files]->type = mrl_sock;
- else {
- this->mrls[num_files]->type = mrl_normal;
- if(mode & S_IXUGO)
- this->mrls[num_files]->type |= mrl_type_exec;
- }
-
+
num_files++;
}
-
+
closedir(pdir);
+
+ /*
+ * Ok, there are some files here, so sort
+ * them then store them into global mrls array.
+ */
+ if(num_files > 0) {
+ int i;
- *nFiles = num_files;
+ num_files = 0;
+
+ /*
+ * Sort arrays
+ */
+ if(num_dir_files)
+ qsort(dir_files, num_dir_files, sizeof(mrl_t), func);
+
+ if(num_hide_files)
+ qsort(hide_files, num_hide_files, sizeof(mrl_t), func);
+
+ if(num_norm_files)
+ qsort(norm_files, num_norm_files, sizeof(mrl_t), func);
+
+ /*
+ * Add directories entries
+ */
+ for(i = 0; i < num_dir_files; i++) {
+
+ if(num_files >= this->mrls_allocated_entries
+ || this->mrls_allocated_entries == 0) {
+ this->mrls[num_files] = (mrl_t *) xmalloc(sizeof(mrl_t));
+ }
+ else
+ memset(this->mrls[num_files], 0, sizeof(mrl_t));
+
+ MRL_DUPLICATE(&dir_files[i], this->mrls[num_files]);
+ num_files++;
+ }
+
+ /*
+ * Add hidden files entries
+ */
+ for(i = 0; i < num_hide_files; i++) {
+
+ if(num_files >= this->mrls_allocated_entries
+ || this->mrls_allocated_entries == 0) {
+ this->mrls[num_files] = (mrl_t *) xmalloc(sizeof(mrl_t));
+ }
+ else
+ memset(this->mrls[num_files], 0, sizeof(mrl_t));
+
+ MRL_DUPLICATE(&hide_files[i], this->mrls[num_files]);
+
+ num_files++;
+ }
+
+ /*
+ * Add other files entries
+ */
+ for(i = 0; i < num_norm_files; i++) {
+
+ if(num_files >= this->mrls_allocated_entries
+ || this->mrls_allocated_entries == 0) {
+ this->mrls[num_files] = (mrl_t *) xmalloc(sizeof(mrl_t));
+ }
+ else
+ memset(this->mrls[num_files], 0, sizeof(mrl_t));
+
+ MRL_DUPLICATE(&norm_files[i], this->mrls[num_files]);
+
+ num_files++;
+ }
+
+ /* Some cleanups before leaving */
+ for(i = num_dir_files; i == 0; i--)
+ MRL_ZERO(&dir_files[i]);
+ free(dir_files);
+
+ for(i = num_hide_files; i == 0; i--)
+ MRL_ZERO(&hide_files[i]);
+ free(hide_files);
+
+ for(i = num_norm_files; i == 0; i--)
+ MRL_ZERO(&norm_files[i]);
+ free(norm_files);
+
+ }
+ else
+ return NULL;
+
+ /*
+ * Inform caller about files found number.
+ */
+ *nFiles = num_files;
+
+ /*
+ * Freeing exceeded mrls if exists.
+ */
if(num_files > this->mrls_allocated_entries)
this->mrls_allocated_entries = num_files;
-
- if(fullpathname)
- free(fullpathname);
+ else if(this->mrls_allocated_entries > num_files) {
+ while(this->mrls_allocated_entries > num_files) {
+ MRL_ZERO(this->mrls[this->mrls_allocated_entries - 1]);
+ free(this->mrls[this->mrls_allocated_entries--]);
+ }
+ }
+ /*
+ * This is useful to let UI know where it should stops ;-).
+ */
this->mrls[num_files] = NULL;
-
+
+ /*
+ * Some debugging info
+ */
+ /*
+ {
+ int j = 0;
+ while(this->mrls[j]) {
+ printf("mrl[%d] = '%s'\n", j, this->mrls[j]->mrl);
+ j++;
+ }
+ }
+ */
+
return this->mrls;
}
@@ -404,7 +708,7 @@ input_plugin_t *init_input_plugin (int iface, config_values_t *config) {
return NULL;
}
- this = (file_input_plugin_t *) malloc (sizeof (file_input_plugin_t));
+ this = (file_input_plugin_t *) xmalloc (sizeof (file_input_plugin_t));
this->input_plugin.interface_version = INPUT_PLUGIN_IFACE_VERSION;
this->input_plugin.get_capabilities = file_plugin_get_capabilities;
@@ -423,14 +727,14 @@ input_plugin_t *init_input_plugin (int iface, config_values_t *config) {
this->input_plugin.get_identifier = file_plugin_get_identifier;
this->input_plugin.get_autoplay_list = NULL;
this->input_plugin.get_optional_data = file_plugin_get_optional_data;
- this->input_plugin.handle_input_event= NULL;
- this->input_plugin.is_branch_possible= NULL;
+ this->input_plugin.handle_input_event = NULL;
+ this->input_plugin.is_branch_possible = NULL;
this->fh = -1;
this->mrl = NULL;
this->config = config;
- this->mrls = (mrl_t **) malloc(sizeof(mrl_t));
+ this->mrls = (mrl_t **) xmalloc(sizeof(mrl_t));
this->mrls_allocated_entries = 0;
return (input_plugin_t *) this;