fixes build system in german (utf-8) locale
[cmus.git] / tabexp_file.c
blobf69a4793662d820cea57af204ba32b6f4f64fcf5
1 /*
2 * Copyright 2004-2005 Timo Hirvonen
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17 * 02111-1307, USA.
20 #include <tabexp_file.h>
21 #include <tabexp.h>
22 #include <load_dir.h>
23 #include <misc.h>
24 #include <xmalloc.h>
25 #include <xstrjoin.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include <pwd.h>
31 #include <dirent.h>
33 static char *get_home(const char *user)
35 struct passwd *passwd;
36 char *home;
37 int len;
39 if (user[0] == 0) {
40 passwd = getpwuid(getuid());
41 } else {
42 passwd = getpwnam(user);
44 if (passwd == NULL)
45 return NULL;
46 len = strlen(passwd->pw_dir);
47 home = xnew(char, len + 2);
48 memcpy(home, passwd->pw_dir, len);
49 home[len] = '/';
50 home[len + 1] = 0;
51 return home;
54 static char *get_full_dir_name(const char *dir)
56 char *full;
58 if (dir[0] == 0) {
59 full = xstrdup("./");
60 } else if (dir[0] == '~') {
61 char *first_slash, *tmp, *home;
63 first_slash = strchr(dir, '/');
64 tmp = xstrndup(dir, first_slash - dir);
65 home = get_home(tmp + 1);
66 free(tmp);
67 if (home == NULL)
68 return NULL;
69 full = xstrjoin(home, first_slash);
70 free(home);
71 } else {
72 full = xstrdup(dir);
74 return full;
77 static const char *starting_with;
79 static int name_filter(const char *name)
81 int len = strlen(starting_with);
83 if (len == 0) {
84 if (name[0] == '.')
85 return 0;
86 } else {
87 if (strncmp(name, starting_with, len))
88 return 0;
90 return 1;
93 static int (*user_filter)(const char *name, const struct stat *s);
95 static int load_dir_filter(const char *name, const struct stat *s)
97 return name_filter(name) && user_filter(name, s);
101 * load all directory entries from directory 'dir' starting with 'start' and
102 * filtered with 'filter'
104 static void tabexp_load_dir(const char *dir, const char *start)
106 char **names;
107 int count;
108 char *full_dir_name;
110 /* for name_filter() */
111 starting_with = start;
113 /* tabexp is resetted */
114 full_dir_name = get_full_dir_name(dir);
115 if (full_dir_name == NULL)
116 return;
118 count = load_dir(full_dir_name, &names, load_dir_filter, strptrcmp);
119 free(full_dir_name);
120 if (count <= 0) {
121 /* opendir failed or no matches */
122 return;
125 tabexp.head = xstrdup(dir);
126 tabexp.tails = names;
127 tabexp.nr_tails = count;
130 void expand_files_and_dirs(const char *src,
131 int (*filter)(const char *name, const struct stat *s))
133 char *slash;
135 /* for load_dir_filter() */
136 user_filter = filter;
138 /* split src to dir and file */
139 slash = strrchr(src, '/');
140 if (slash) {
141 char *dir;
142 const char *file;
144 /* split */
145 dir = xstrndup(src, slash - src + 1);
146 file = slash + 1;
147 /* get all dentries starting with file from dir */
148 tabexp_load_dir(dir, file);
149 free(dir);
150 } else {
151 if (src[0] == '~') {
152 char *home = get_home(src + 1);
154 if (home) {
155 tabexp.head = xstrdup("");
156 tabexp.nr_tails = 1;
157 tabexp.tails = xnew(char *, 2);
158 tabexp.tails[0] = home;
159 tabexp.tails[1] = NULL;
161 } else {
162 tabexp_load_dir("", src);