xref: /aosp_15_r20/external/mtools/unixdir.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
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 "file.h"
23 #include "htable.h"
24 #include "mainloop.h"
25 #include <dirent.h>
26 
27 typedef struct Dir_t {
28 	struct Stream_t head;
29 
30 	struct MT_STAT statbuf;
31 	char *pathname;
32 	DIR *dir;
33 #ifdef HAVE_FCHDIR
34 	int fd;
35 #endif
36 } Dir_t;
37 
38 /*#define FCHDIR_MODE*/
39 
get_dir_data(Stream_t * Stream,time_t * date,mt_off_t * size,int * type,unsigned int * address)40 static int get_dir_data(Stream_t *Stream, time_t *date, mt_off_t *size,
41 			int *type, unsigned int *address)
42 {
43 	DeclareThis(Dir_t);
44 
45 	if(date)
46 		*date = This->statbuf.st_mtime;
47 	if(size)
48 		*size = This->statbuf.st_size;
49 	if(type)
50 		*type = 1;
51 	if(address)
52 		*address = 0;
53 	return 0;
54 }
55 
dir_free(Stream_t * Stream)56 static int dir_free(Stream_t *Stream)
57 {
58 	DeclareThis(Dir_t);
59 
60 	Free(This->pathname);
61 	closedir(This->dir);
62 	return 0;
63 }
64 
65 static Class_t DirClass = {
66 	0, /* read */
67 	0, /* write */
68 	0, /* pread */
69 	0, /* pwrite */
70 	0, /* flush */
71 	dir_free, /* free */
72 	0, /* get_geom */
73 	get_dir_data ,
74 	0, /* pre-allocate */
75 	0, /* get_dosConvert */
76 	0 /* discard */
77 };
78 
79 #ifdef HAVE_FCHDIR
80 #define FCHDIR_MODE
81 #endif
82 
83 int unix_dir_loop(Stream_t *Stream, MainParam_t *mp);
84 int unix_loop(Stream_t *Stream, MainParam_t *mp, char *arg,
85 	      int follow_dir_link);
86 
unix_dir_loop(Stream_t * Stream,MainParam_t * mp)87 int 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 	if(chdir(This->pathname) < 0) {
99 		fprintf(stderr, "Could not chdir into %s (%s)\n",
100 			This->pathname, strerror(errno));
101 		return -1;
102 	}
103 #endif
104 	while((entry=readdir(This->dir)) != NULL) {
105 		if(got_signal)
106 			break;
107 		if(isSpecial(entry->d_name))
108 			continue;
109 #ifndef FCHDIR_MODE
110 		newName = malloc(strlen(This->pathname) + 1 +
111 				 strlen(entry->d_name) + 1);
112 		if(!newName) {
113 			ret = ERROR_ONE;
114 			break;
115 		}
116 		strcpy(newName, This->pathname);
117 		strcat(newName, "/");
118 		strcat(newName, entry->d_name);
119 #else
120 		newName = entry->d_name;
121 #endif
122 		ret |= unix_loop(Stream, mp, newName, 0);
123 #ifndef FCHDIR_MODE
124 		free(newName);
125 #endif
126 	}
127 #ifdef FCHDIR_MODE
128 	if(fchdir(fd) < 0)
129 		perror("Could not chdir back to ..");
130 	close(fd);
131 #endif
132 	return ret;
133 }
134 
OpenDir(const char * filename)135 Stream_t *OpenDir(const char *filename)
136 {
137 	Dir_t *This;
138 
139 	This = New(Dir_t);
140 	init_head(&This->head, &DirClass, NULL);
141 	This->pathname = malloc(strlen(filename)+1);
142 	if(This->pathname == NULL) {
143 		Free(This);
144 		return NULL;
145 	}
146 	strcpy(This->pathname, filename);
147 
148 	if(MT_STAT(filename, &This->statbuf) < 0) {
149 		Free(This->pathname);
150 		Free(This);
151 		return NULL;
152 	}
153 
154 	This->dir = opendir(filename);
155 	if(!This->dir) {
156 		Free(This->pathname);
157 		Free(This);
158 		return NULL;
159 	}
160 
161 	return &This->head;
162 }
163