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/* pling added start 06/24/2009 */ 52/* Calculcate the real file size based on stat info */ 53static unsigned long long get_real_file_size(struct stat *st) 54{ 55 unsigned long long file_size_64; 56 unsigned long long order; 57 58 /* Check whether file size > 4GB which exceeds 32-bit st->st_size 59 * st->sb_blocks in units of 512 bytes. 60 * If 'st->sb_blocks' x 512 > 4GB, then this file > 4GB. 61 */ 62 if (st->st_blocks >= 8388608L) 63 { 64 order = st->st_blocks / 8388608L; // order = # of 4GB 65 file_size_64 = 0x100000000 * order + (unsigned long)(st->st_size); 66 } 67 else 68 file_size_64 = st->st_size & 0xFFFFFFFF; 69 70 //printf("file_size_64 = %llu\n", file_size_64); 71 72 return file_size_64; 73} 74/* pling added end 06/24/2009 */ 75 76struct hidegroup *hidegroups = NULL; 77 78void add_to_hidegroups(int gid) 79{ 80 static struct hidegroup *tmp = NULL; 81 if (tmp) 82 tmp = tmp->next = malloc(sizeof(struct hidegroup)); 83 else 84 hidegroups = tmp = malloc(sizeof(struct hidegroup)); 85 86 if (tmp) 87 { 88 tmp->next = NULL; 89 tmp->data = gid; 90 } 91} 92 93void hidegroups_init() 94{ 95 char *foo = strdup(config_getoption("HIDE_GROUP")); 96 char *foo_save = foo; 97 char *bar; 98 struct group *tmpgrp; 99 100 while ((bar = strtok(foo, ","))) { 101 foo = NULL; /* strtok requirement */ 102 if ((strcmp(bar, "0")) && (!strtoul(bar, NULL, 10))) { 103 /* bar is not numeric */ 104 if ((tmpgrp = getgrnam(bar))) 105 add_to_hidegroups(tmpgrp->gr_gid); 106 } else 107 if (strtoul(bar, NULL, 10)) 108 add_to_hidegroups(strtoul(bar, NULL, 10)); 109 } 110 free(foo_save); 111} 112 113void hidegroups_end() 114{ 115 struct hidegroup *tmp = hidegroups; 116 if (hidegroups) 117 while (hidegroups->next) { 118 tmp = hidegroups->next; 119 free(hidegroups); 120 hidegroups = tmp; 121 } 122} 123 124/* Foxconn added start pling 06/20/2009 */ 125#include "logging.h" 126int is_dir_allow_read(char *dir_name) 127{ 128 char curr_dir[1024]; 129 int allow_read = 0; 130 131 /* Change to the specified dir, and see if the 132 * "ALLOWCOMMAND_LIST" is enabled or not. 133 */ 134 memset(curr_dir, 0, sizeof(curr_dir)); 135 getcwd(curr_dir, sizeof(curr_dir)-1); 136 137 bftpd_log("Cwd='%s', checking '%s' for admin-read\n", curr_dir, dir_name); 138 139 if (chdir(dir_name)) 140 bftpd_log("Unable to chdir '%s', errno=%d\n", dir_name, errno); 141 else 142 { 143 if (!strcasecmp(getoption_user("ALLOWCOMMAND_LIST"), "yes")) 144 allow_read = 1; 145 chdir(curr_dir); 146 } 147 148 return allow_read; 149} 150/* Foxconn added end pling 06/20/2009 */ 151 152void bftpd_stat(char *name, FILE * client) 153{ 154 struct stat statbuf; 155 char temp[MAXCMD + 3], linktarget[MAXCMD + 5], perm[11], timestr[17], uid[USERLEN + 1], gid[USERLEN + 1]; 156 struct tm filetime; 157 time_t t; 158 static int first_time = 1; /* Foxconn added pling 06/28/2010 */ 159 160 161 if (lstat(name, (struct stat *) &statbuf) == -1) { // used for command_stat 162 fprintf(client, "213-Error: %s.\n", strerror(errno)); 163 return; 164 } 165 166#if 0 167 /* Foxconn added start pling 06/20/2009 */ 168 /* Don't let 'guest' user see "Admin-read" folders */ 169 if (S_ISDIR(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) 170 { 171 if (!is_dir_allow_read(name)) 172 return; 173 } 174 /* Foxconn added end pling 06/20/2009 */ 175#endif 176 177 //if ( strcmp(user, "admin") != 0 ) { 178 // if ( !is_dir_allow_read(name) ) 179 // return; 180 //} 181 182#ifdef S_ISLNK 183 if (S_ISLNK(statbuf.st_mode)) { 184 /* Foxconn modified start pling 03/09/2010 */ 185 /* Show links as directories, other Safari can't 186 * handle links properly. 187 * Note: in FAT32/NTFS, there are no links. 188 * This link is either "USB_Storage", "T_Drive" 189 * or other share names that user defines. 190 */ 191 //strcpy(perm, "lrwxrwxrwx"); 192 strcpy(perm, "drwxrwxrwx"); 193 /* Foxconn modified end pling 03/09/2010 */ 194 /* Foxconn modified start pling 06/20/2009 */ 195 /* Don't show symlink */ 196#if 0 197 temp[readlink(name, temp, sizeof(temp) - 1)] = '\0'; 198 sprintf(linktarget, " -> %s", temp); 199#endif 200 linktarget[0] = '\0'; 201 /* Foxconn modified end pling 06/20/2009 */ 202 } else { 203#endif 204 strcpy(perm, "----------"); 205 if (S_ISDIR(statbuf.st_mode)) 206 perm[0] = 'd'; 207 if (statbuf.st_mode & S_IRUSR) 208 perm[1] = 'r'; 209 if (statbuf.st_mode & S_IWUSR) 210 perm[2] = 'w'; 211 if (statbuf.st_mode & S_IXUSR) 212 perm[3] = 'x'; 213 if (statbuf.st_mode & S_IRGRP) 214 perm[4] = 'r'; 215 if (statbuf.st_mode & S_IWGRP) 216 perm[5] = 'w'; 217 if (statbuf.st_mode & S_IXGRP) 218 perm[6] = 'x'; 219 if (statbuf.st_mode & S_IROTH) 220 perm[7] = 'r'; 221 if (statbuf.st_mode & S_IWOTH) 222 perm[8] = 'w'; 223 if (statbuf.st_mode & S_IXOTH) 224 perm[9] = 'x'; 225 linktarget[0] = '\0'; 226#ifdef S_ISLNK 227 } 228#endif 229 memcpy(&filetime, localtime(&(statbuf.st_mtime)), sizeof(struct tm)); 230 time(&t); 231 if (filetime.tm_year == localtime(&t)->tm_year) 232 mystrncpy(timestr, ctime(&(statbuf.st_mtime)) + 4, 12); 233 else 234 strftime(timestr, sizeof(timestr), "%b %d %G", &filetime); 235 mygetpwuid(statbuf.st_uid, passwdfile, uid)[8] = 0; 236 mygetpwuid(statbuf.st_gid, groupfile, gid)[8] = 0; 237 238 /* Foxconn added start pling 06/28/2010 */ 239 /* Fix Chrome V4.0.249.78 FTP issue; 240 * need to provide a "." directory entry for Chrome to 241 * show properly. 242 */ 243 if (first_time) 244 { 245 fprintf(client, "%s %3i %-8s %-8s 0 %s .\r\n", "drwxrwxrwx", 246 (int) 1, uid, gid, 247 timestr); 248 first_time = 0; 249 } 250 /* Foxconn added end pling 06/28/2010 */ 251 252 /* Foxconn modified start pling 06/29/2009 */ 253 /* Show big file size (>4GB) correctly */ 254#if 0 255 fprintf(client, "%s %3i %-8s %-8s %8lu %s %s%s\r\n", perm, 256 (int) statbuf.st_nlink, uid, gid, 257 (unsigned long) statbuf.st_size, 258 timestr, name, linktarget); 259#endif 260 unsigned long long real_file_size = get_real_file_size(&statbuf); 261 fprintf(client, "%s %3i %-8s %-8s %llu %s %s%s\r\n", perm, 262 (int) statbuf.st_nlink, uid, gid, 263 (unsigned long long) real_file_size, 264 timestr, name, linktarget); 265 /* Foxconn modified end pling 06/29/2009 */ 266} 267 268void dirlist_one_file(char *name, FILE *client, char verbose) 269{ 270 struct stat statbuf; 271 struct hidegroup *tmp = hidegroups; 272 char *filename_index; /* place where filename starts in path */ 273 274 if (!stat(name, (struct stat *) &statbuf)) { 275 if (tmp) 276 do { 277 if (statbuf.st_gid == tmp->data) 278 return; 279 } while ((tmp = tmp->next)); 280 } 281 282 /* find start of filename after path */ 283 filename_index = strrchr(name, '/'); 284 if (filename_index) 285 filename_index++; /* goto first character after '/' */ 286 else 287 filename_index = name; 288 289 if (lstat(name, (struct stat *) &statbuf) == -1) { // used for command_stat 290 fprintf(client, "213-Error: %s.\n", strerror(errno)); 291 return; 292 } 293 294 /* Foxconn added start pling 06/20/2009 */ 295 /* Don't let 'guest' user see "Admin-read" folders */ 296 if (S_ISDIR(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) 297 { 298 if (!is_dir_allow_read(name)) 299 return; 300 } 301 /* Foxconn added end pling 06/20/2009 */ 302 303 if (verbose) 304 bftpd_stat(name, client); 305 else 306 fprintf(client, "%s\r\n", filename_index); 307} 308 309void dirlist(char *name, FILE * client, char verbose) 310{ 311 DIR *directory; 312 char *cwd = NULL; 313 int i; 314 glob_t globbuf; 315 if ((strstr(name, "/.")) && strchr(name, '*')) 316 return; /* DoS protection */ 317 if ((directory = opendir(name))) { 318 closedir(directory); 319 cwd = bftpd_cwd_getcwd(); 320 chdir(name); 321 glob("*", 0, NULL, &globbuf); 322 } else 323 glob(name, 0, NULL, &globbuf); 324 325 for (i = 0; i < globbuf.gl_pathc; i++) 326 dirlist_one_file(globbuf.gl_pathv[i], client, verbose); 327 328 globfree(&globbuf); 329 if (cwd) { 330 chdir(cwd); 331 free(cwd); 332 } 333} 334