xref: /aosp_15_r20/external/mtools/unixdir.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
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