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