# BRCM_VERSION=3
[bcm963xx.git] / userapps / opensource / ftpd / dirlist.c
1 #include <config.h>
2 #include <stdio.h>
3 #ifdef HAVE_SYS_TYPES_H
4 #include <sys/types.h>
5 #endif
6 #ifdef HAVE_SYS_SOCKET_H
7 #include <sys/socket.h>
8 #endif
9
10 #ifdef HAVE_DIRENT_H
11 #  include <dirent.h>
12 #else
13 #    define dirent direct
14 #    define NAMLEN(dirent) (dirent)->d_namlen
15 #  ifdef HAVE_SYS_NDIR_H
16 #    include <sys/ndir.h>
17 #  endif
18 #  ifdef HAVE_SYS_DIR_H
19 #    include <sys/dir.h>
20 #  endif
21 #  ifdef HAVE_NDIR_H
22 #    include <ndir.h>
23 #  endif
24 #endif
25
26 #include <unistd.h>
27 #ifdef HAVE_SYS_STAT_H
28 #include <sys/stat.h>
29 #endif
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #include <mystring.h>
34 #ifdef HAVE_SYS_TIME_H
35 #include <sys/time.h>
36 #endif
37 #ifdef HAVE_TIME_H
38 #include <time.h>
39 #endif
40 #include <pwd.h>
41 #include <grp.h>
42 #include <errno.h>
43 #include <glob.h>
44
45 #include "cwd.h"
46 #include "options.h"
47 #include "main.h"
48 #include "login.h"
49 #include "dirlist.h"
50
51 struct hidegroup *hidegroups = NULL;
52
53 void add_to_hidegroups(int gid)
54 {
55     static struct hidegroup *tmp = NULL;
56     if (tmp)
57         tmp = tmp->next = malloc(sizeof(struct hidegroup));
58     else
59         hidegroups = tmp = malloc(sizeof(struct hidegroup));
60     tmp->next = NULL;
61     tmp->data = gid;
62 }
63
64 void hidegroups_init()
65 {
66     char *foo = strdup(config_getoption("HIDE_GROUP"));
67         char *foo_save = foo;
68     char *bar;
69     struct group *tmpgrp;
70     while ((bar = strtok(foo, ","))) {
71         foo = NULL; /* strtok requirement */
72         if ((strcmp(bar, "0")) && (!strtoul(bar, NULL, 10))) {
73             /* bar is not numeric */
74             if ((tmpgrp = getgrnam(bar)))
75                 add_to_hidegroups(tmpgrp->gr_gid);
76         } else
77             if (strtoul(bar, NULL, 10))
78                 add_to_hidegroups(strtoul(bar, NULL, 10));
79     }
80         free(foo_save);
81 }
82
83 void hidegroups_end()
84 {
85     struct hidegroup *tmp = hidegroups;
86     if (hidegroups)
87         while (hidegroups->next) {
88             tmp = hidegroups->next;
89             free(hidegroups);
90             hidegroups = tmp;
91         }
92 }
93
94 void bftpd_stat(char *name, FILE * client)
95 {
96     struct stat statbuf;
97         char temp[MAXCMD + 3], linktarget[MAXCMD + 5], perm[11], timestr[17],
98                 uid[USERLEN + 1], gid[USERLEN + 1];
99     struct tm filetime;
100     time_t t;
101     if (lstat(name, (struct stat *) &statbuf) == -1) { // used for command_stat
102         fprintf(client, "213-Error: %s.\n", strerror(errno));
103         return;
104     }
105 #ifdef S_ISLNK
106         if (S_ISLNK(statbuf.st_mode)) {
107                 strcpy(perm, "lrwxrwxrwx");
108                 temp[readlink(name, temp, sizeof(temp) - 1)] = '\0';
109                 sprintf(linktarget, " -> %s", temp);
110         } else {
111 #endif
112                 strcpy(perm, "----------");
113                 if (S_ISDIR(statbuf.st_mode))
114                         perm[0] = 'd';
115                 if (statbuf.st_mode & S_IRUSR)
116                         perm[1] = 'r';
117                 if (statbuf.st_mode & S_IWUSR)
118                         perm[2] = 'w';
119                 if (statbuf.st_mode & S_IXUSR)
120                         perm[3] = 'x';
121                 if (statbuf.st_mode & S_IRGRP)
122                         perm[4] = 'r';
123                 if (statbuf.st_mode & S_IWGRP)
124                         perm[5] = 'w';
125                 if (statbuf.st_mode & S_IXGRP)
126                         perm[6] = 'x';
127                 if (statbuf.st_mode & S_IROTH)
128                         perm[7] = 'r';
129                 if (statbuf.st_mode & S_IWOTH)
130                         perm[8] = 'w';
131                 if (statbuf.st_mode & S_IXOTH)
132                         perm[9] = 'x';
133                 linktarget[0] = '\0';
134 #ifdef S_ISLNK
135         }
136 #endif
137     memcpy(&filetime, localtime(&(statbuf.st_mtime)), sizeof(struct tm));
138     time(&t);
139     if (filetime.tm_year == localtime(&t)->tm_year)
140         mystrncpy(timestr, ctime(&(statbuf.st_mtime)) + 4, 12);
141     else
142         strftime(timestr, sizeof(timestr), "%b %d  %G", &filetime);
143     mygetpwuid(statbuf.st_uid, passwdfile, uid)[8] = 0;
144     mygetpwuid(statbuf.st_gid, groupfile, gid)[8] = 0;
145         fprintf(client, "%s %3i %-8s %-8s %8lu %s %s%s\r\n", perm,
146                         (int) statbuf.st_nlink, uid, gid,
147                         (unsigned long) statbuf.st_size,
148                         timestr, name, linktarget);
149 }
150
151 void dirlist_one_file(char *name, FILE *client, char verbose)
152 {
153     struct stat statbuf;
154     struct hidegroup *tmp = hidegroups;
155     if (!stat(name, (struct stat *) &statbuf)) {
156         if (tmp)
157             do {
158                 if (statbuf.st_gid == tmp->data)
159                     return;
160             } while ((tmp = tmp->next));
161     }
162     if (verbose)
163         bftpd_stat(name, client);
164     else
165         fprintf(client, "%s\r\n", name);
166 }
167
168 void dirlist(char *name, FILE * client, char verbose)
169 {
170         DIR *directory;
171     char *cwd = NULL;
172     int i;
173         glob_t globbuf;
174     if ((strstr(name, "/.")) && strchr(name, '*'))
175         return; /* DoS protection */
176         if ((directory = opendir(name))) {
177                 closedir(directory);
178         cwd = bftpd_cwd_getcwd();
179         chdir(name);
180         glob("*", 0, NULL, &globbuf);
181         } else
182         glob(name, 0, NULL, &globbuf);
183         for (i = 0; i < globbuf.gl_pathc; i++)
184         dirlist_one_file(globbuf.gl_pathv[i], client, verbose);
185         globfree(&globbuf);
186         if (cwd) {
187                 chdir(cwd);
188                 free(cwd);
189         }
190 }