/* Copyright 1998-2002,2009 Alain Knaff. * This file is part of mtools. * * Mtools is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Mtools is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Mtools. If not, see . */ #include "sysincludes.h" #include "msdos.h" #include "stream.h" #include "mtools.h" #include "fsP.h" #include "file.h" #include "htable.h" #include "mainloop.h" #include typedef struct Dir_t { Class_t *Class; int refs; Stream_t *Next; Stream_t *Buffer; struct MT_STAT statbuf; char *pathname; DIR *dir; #ifdef HAVE_FCHDIR int fd; #endif } Dir_t; /*#define FCHDIR_MODE*/ static int get_dir_data(Stream_t *Stream, time_t *date, mt_size_t *size, int *type, int *address) { DeclareThis(Dir_t); if(date) *date = This->statbuf.st_mtime; if(size) *size = (mt_size_t) This->statbuf.st_size; if(type) *type = 1; if(address) *address = 0; return 0; } static int dir_free(Stream_t *Stream) { DeclareThis(Dir_t); Free(This->pathname); closedir(This->dir); return 0; } static Class_t DirClass = { 0, /* read */ 0, /* write */ 0, /* flush */ dir_free, /* free */ 0, /* get_geom */ get_dir_data , 0, /* pre-allocate */ 0, /* get_dosConvert */ 0 /* discard */ }; #ifdef HAVE_FCHDIR #define FCHDIR_MODE #endif int unix_dir_loop(Stream_t *Stream, MainParam_t *mp); int unix_loop(Stream_t *Stream, MainParam_t *mp, char *arg, int follow_dir_link); int unix_dir_loop(Stream_t *Stream, MainParam_t *mp) { DeclareThis(Dir_t); struct dirent *entry; char *newName; int ret=0; #ifdef FCHDIR_MODE int fd; fd = open(".", O_RDONLY); if(chdir(This->pathname) < 0) { fprintf(stderr, "Could not chdir into %s (%s)\n", This->pathname, strerror(errno)); return -1; } #endif while((entry=readdir(This->dir)) != NULL) { if(got_signal) break; if(isSpecial(entry->d_name)) continue; #ifndef FCHDIR_MODE newName = malloc(strlen(This->pathname) + 1 + strlen(entry->d_name) + 1); if(!newName) { ret = ERROR_ONE; break; } strcpy(newName, This->pathname); strcat(newName, "/"); strcat(newName, entry->d_name); #else newName = entry->d_name; #endif ret |= unix_loop(Stream, mp, newName, 0); #ifndef FCHDIR_MODE free(newName); #endif } #ifdef FCHDIR_MODE if(fchdir(fd) < 0) perror("Could not chdir back to .."); close(fd); #endif return ret; } Stream_t *OpenDir(const char *filename) { Dir_t *This; This = New(Dir_t); This->Class = &DirClass; This->Next = 0; This->refs = 1; This->Buffer = 0; This->pathname = malloc(strlen(filename)+1); if(This->pathname == NULL) { Free(This); return NULL; } strcpy(This->pathname, filename); if(MT_STAT(filename, &This->statbuf) < 0) { Free(This->pathname); Free(This); return NULL; } This->dir = opendir(filename); if(!This->dir) { Free(This->pathname); Free(This); return NULL; } return (Stream_t *) This; }