1/* Copyright 1998-2002,2009 Alain Knaff. 2 * This file is part of mtools. 3 * 4 * Mtools is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * Mtools 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 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with Mtools. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18#include "sysincludes.h" 19#include "msdos.h" 20#include "stream.h" 21#include "mtools.h" 22#include "fsP.h" 23#include "file.h" 24#include "htable.h" 25#include "mainloop.h" 26#include <dirent.h> 27 28typedef struct Dir_t { 29 Class_t *Class; 30 int refs; 31 Stream_t *Next; 32 Stream_t *Buffer; 33 34 struct MT_STAT statbuf; 35 char *pathname; 36 DIR *dir; 37#ifdef HAVE_FCHDIR 38 int fd; 39#endif 40} Dir_t; 41 42/*#define FCHDIR_MODE*/ 43 44static int get_dir_data(Stream_t *Stream, time_t *date, mt_size_t *size, 45 int *type, int *address) 46{ 47 DeclareThis(Dir_t); 48 49 if(date) 50 *date = This->statbuf.st_mtime; 51 if(size) 52 *size = (mt_size_t) This->statbuf.st_size; 53 if(type) 54 *type = 1; 55 if(address) 56 *address = 0; 57 return 0; 58} 59 60static int dir_free(Stream_t *Stream) 61{ 62 DeclareThis(Dir_t); 63 64 Free(This->pathname); 65 closedir(This->dir); 66 return 0; 67} 68 69static Class_t DirClass = { 70 0, /* read */ 71 0, /* write */ 72 0, /* flush */ 73 dir_free, /* free */ 74 0, /* get_geom */ 75 get_dir_data , 76 0 /* pre-allocate */ 77}; 78 79#ifdef HAVE_FCHDIR 80#define FCHDIR_MODE 81#endif 82 83int unix_dir_loop(Stream_t *Stream, MainParam_t *mp); 84int unix_loop(Stream_t *Stream, MainParam_t *mp, char *arg, 85 int follow_dir_link); 86 87int unix_dir_loop(Stream_t *Stream, MainParam_t *mp) 88{ 89 DeclareThis(Dir_t); 90 struct dirent *entry; 91 char *newName; 92 int ret=0; 93 94#ifdef FCHDIR_MODE 95 int fd; 96 97 fd = open(".", O_RDONLY); 98 chdir(This->pathname); 99#endif 100 while((entry=readdir(This->dir)) != NULL) { 101 if(got_signal) 102 break; 103 if(isSpecial(entry->d_name)) 104 continue; 105#ifndef FCHDIR_MODE 106 newName = malloc(strlen(This->pathname) + 1 + 107 strlen(entry->d_name) + 1); 108 if(!newName) { 109 ret = ERROR_ONE; 110 break; 111 } 112 strcpy(newName, This->pathname); 113 strcat(newName, "/"); 114 strcat(newName, entry->d_name); 115#else 116 newName = entry->d_name; 117#endif 118 ret |= unix_loop(Stream, mp, newName, 0); 119#ifndef FCHDIR_MODE 120 free(newName); 121#endif 122 } 123#ifdef FCHDIR_MODE 124 fchdir(fd); 125 close(fd); 126#endif 127 return ret; 128} 129 130Stream_t *OpenDir(Stream_t *Stream, const char *filename) 131{ 132 Dir_t *This; 133 134 This = New(Dir_t); 135 136 This->Class = &DirClass; 137 This->Next = 0; 138 This->refs = 1; 139 This->Buffer = 0; 140 This->pathname = malloc(strlen(filename)+1); 141 if(This->pathname == NULL) { 142 Free(This); 143 return NULL; 144 } 145 strcpy(This->pathname, filename); 146 147 if(MT_STAT(filename, &This->statbuf) < 0) { 148 Free(This->pathname); 149 Free(This); 150 return NULL; 151 } 152 153 This->dir = opendir(filename); 154 if(!This->dir) { 155 Free(This->pathname); 156 Free(This); 157 return NULL; 158 } 159 160 return (Stream_t *) This; 161} 162