xref: /aosp_15_r20/external/mtools/direntry.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
1*d5c9a868SElliott Hughes /*  Copyright 1997,2000-2003,2007-2010 Alain Knaff.  This file is
2*d5c9a868SElliott Hughes  *  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 "file.h"
22*d5c9a868SElliott Hughes #include "mtoolsDirentry.h"
23*d5c9a868SElliott Hughes #include "file_name.h"
24*d5c9a868SElliott Hughes 
initializeDirentry(direntry_t * entry,Stream_t * Dir)25*d5c9a868SElliott Hughes void initializeDirentry(direntry_t *entry, Stream_t *Dir)
26*d5c9a868SElliott Hughes {
27*d5c9a868SElliott Hughes 	memset(entry, 0, sizeof(direntry_t));
28*d5c9a868SElliott Hughes 	entry->entry = -1;
29*d5c9a868SElliott Hughes 	entry->Dir = Dir;
30*d5c9a868SElliott Hughes 	entry->beginSlot = 0;
31*d5c9a868SElliott Hughes 	entry->endSlot = 0;
32*d5c9a868SElliott Hughes }
33*d5c9a868SElliott Hughes 
isNotFound(direntry_t * entry)34*d5c9a868SElliott Hughes int isNotFound(direntry_t *entry)
35*d5c9a868SElliott Hughes {
36*d5c9a868SElliott Hughes 	return entry->entry == -2;
37*d5c9a868SElliott Hughes }
38*d5c9a868SElliott Hughes 
getParent(direntry_t * entry)39*d5c9a868SElliott Hughes direntry_t *getParent(direntry_t *entry)
40*d5c9a868SElliott Hughes {
41*d5c9a868SElliott Hughes 	return getDirentry(entry->Dir);
42*d5c9a868SElliott Hughes }
43*d5c9a868SElliott Hughes 
44*d5c9a868SElliott Hughes 
getPathLen(direntry_t * entry)45*d5c9a868SElliott Hughes static size_t getPathLen(direntry_t *entry)
46*d5c9a868SElliott Hughes {
47*d5c9a868SElliott Hughes 	size_t length=0;
48*d5c9a868SElliott Hughes 
49*d5c9a868SElliott Hughes 	while(1) {
50*d5c9a868SElliott Hughes 		if(entry->entry == -3) /* rootDir */
51*d5c9a868SElliott Hughes 			return length + 3;
52*d5c9a868SElliott Hughes 
53*d5c9a868SElliott Hughes 		length += 1 + wcslen(entry->name);
54*d5c9a868SElliott Hughes 		entry = getDirentry(entry->Dir);
55*d5c9a868SElliott Hughes 	}
56*d5c9a868SElliott Hughes }
57*d5c9a868SElliott Hughes 
sprintPwd(direntry_t * entry,char * ptr,size_t * len_available)58*d5c9a868SElliott Hughes static char *sprintPwd(direntry_t *entry, char *ptr, size_t *len_available)
59*d5c9a868SElliott Hughes {
60*d5c9a868SElliott Hughes 	if(entry->entry == -3) {
61*d5c9a868SElliott Hughes 		*ptr++ = getDrive(entry->Dir);
62*d5c9a868SElliott Hughes 		*ptr++ = ':';
63*d5c9a868SElliott Hughes 		*ptr++ = '/';
64*d5c9a868SElliott Hughes 		(*len_available) -= 3;
65*d5c9a868SElliott Hughes 	} else {
66*d5c9a868SElliott Hughes 		size_t bytes_converted;
67*d5c9a868SElliott Hughes 		ptr = sprintPwd(getDirentry(entry->Dir), ptr, len_available);
68*d5c9a868SElliott Hughes 		if(ptr[-1] != '/') {
69*d5c9a868SElliott Hughes 			*ptr++ = '/';
70*d5c9a868SElliott Hughes 			(*len_available)--;
71*d5c9a868SElliott Hughes 		}
72*d5c9a868SElliott Hughes 		bytes_converted = wchar_to_native(entry->name, ptr,
73*d5c9a868SElliott Hughes 						  MAX_VNAMELEN, *len_available);
74*d5c9a868SElliott Hughes 		ptr += bytes_converted;
75*d5c9a868SElliott Hughes 		(*len_available) -= bytes_converted;
76*d5c9a868SElliott Hughes 	}
77*d5c9a868SElliott Hughes 	return ptr;
78*d5c9a868SElliott Hughes }
79*d5c9a868SElliott Hughes 
80*d5c9a868SElliott Hughes 
81*d5c9a868SElliott Hughes #ifdef HAVE_WCHAR_H
82*d5c9a868SElliott Hughes #define NEED_ESCAPE L"\"$\\"
83*d5c9a868SElliott Hughes #else
84*d5c9a868SElliott Hughes #define NEED_ESCAPE "\"$\\"
85*d5c9a868SElliott Hughes #endif
86*d5c9a868SElliott Hughes 
_fprintPwd(FILE * f,direntry_t * entry,int recurs,int escape)87*d5c9a868SElliott Hughes static void _fprintPwd(FILE *f, direntry_t *entry, int recurs, int escape)
88*d5c9a868SElliott Hughes {
89*d5c9a868SElliott Hughes 	if(entry->entry == -3) {
90*d5c9a868SElliott Hughes 		putc(getDrive(entry->Dir), f);
91*d5c9a868SElliott Hughes 		putc(':', f);
92*d5c9a868SElliott Hughes 		if(!recurs)
93*d5c9a868SElliott Hughes 			putc('/', f);
94*d5c9a868SElliott Hughes 	} else {
95*d5c9a868SElliott Hughes 		_fprintPwd(f, getDirentry(entry->Dir), 1, escape);
96*d5c9a868SElliott Hughes 		if (escape && wcspbrk(entry->name, NEED_ESCAPE)) {
97*d5c9a868SElliott Hughes 			wchar_t *ptr;
98*d5c9a868SElliott Hughes 			putc('/', f);
99*d5c9a868SElliott Hughes 			for(ptr = entry->name; *ptr; ptr++) {
100*d5c9a868SElliott Hughes 				if (wcschr(NEED_ESCAPE, *ptr))
101*d5c9a868SElliott Hughes 					putc('\\', f);
102*d5c9a868SElliott Hughes 				putwc(*ptr, f);
103*d5c9a868SElliott Hughes 			}
104*d5c9a868SElliott Hughes 		} else {
105*d5c9a868SElliott Hughes 			char tmp[4*MAX_VNAMELEN+1];
106*d5c9a868SElliott Hughes 			WCHAR_TO_NATIVE(entry->name,tmp,MAX_VNAMELEN);
107*d5c9a868SElliott Hughes 			fprintf(f, "/%s", tmp);
108*d5c9a868SElliott Hughes 		}
109*d5c9a868SElliott Hughes 	}
110*d5c9a868SElliott Hughes }
111*d5c9a868SElliott Hughes 
fprintPwd(FILE * f,direntry_t * entry,int escape)112*d5c9a868SElliott Hughes void fprintPwd(FILE *f, direntry_t *entry, int escape)
113*d5c9a868SElliott Hughes {
114*d5c9a868SElliott Hughes 	if (escape)
115*d5c9a868SElliott Hughes 		putc('"', f);
116*d5c9a868SElliott Hughes 	_fprintPwd(f, entry, 0, escape);
117*d5c9a868SElliott Hughes 	if(escape)
118*d5c9a868SElliott Hughes 		putc('"', f);
119*d5c9a868SElliott Hughes }
120*d5c9a868SElliott Hughes 
_fprintShortPwd(FILE * f,direntry_t * entry,int recurs)121*d5c9a868SElliott Hughes static void _fprintShortPwd(FILE *f, direntry_t *entry, int recurs)
122*d5c9a868SElliott Hughes {
123*d5c9a868SElliott Hughes 	if(entry->entry == -3) {
124*d5c9a868SElliott Hughes 		putc(getDrive(entry->Dir), f);
125*d5c9a868SElliott Hughes 		putc(':', f);
126*d5c9a868SElliott Hughes 		if(!recurs)
127*d5c9a868SElliott Hughes 			putc('/', f);
128*d5c9a868SElliott Hughes 	} else {
129*d5c9a868SElliott Hughes 		int i,j;
130*d5c9a868SElliott Hughes 		_fprintShortPwd(f, getDirentry(entry->Dir), 1);
131*d5c9a868SElliott Hughes 		putc('/',f);
132*d5c9a868SElliott Hughes 		for(i=7; i>=0 && entry->dir.name[i] == ' ';i--);
133*d5c9a868SElliott Hughes 		for(j=0; j<=i; j++)
134*d5c9a868SElliott Hughes 			putc(entry->dir.name[j],f);
135*d5c9a868SElliott Hughes 		for(i=2; i>=0 && entry->dir.ext[i] == ' ';i--);
136*d5c9a868SElliott Hughes 		if(i > 0)
137*d5c9a868SElliott Hughes 			putc('.',f);
138*d5c9a868SElliott Hughes 		for(j=0; j<=i; j++)
139*d5c9a868SElliott Hughes 			putc(entry->dir.ext[j],f);
140*d5c9a868SElliott Hughes 	}
141*d5c9a868SElliott Hughes }
142*d5c9a868SElliott Hughes 
fprintShortPwd(FILE * f,direntry_t * entry)143*d5c9a868SElliott Hughes void fprintShortPwd(FILE *f, direntry_t *entry)
144*d5c9a868SElliott Hughes {
145*d5c9a868SElliott Hughes 	_fprintShortPwd(f, entry, 0);
146*d5c9a868SElliott Hughes }
147*d5c9a868SElliott Hughes 
getPwd(direntry_t * entry)148*d5c9a868SElliott Hughes char *getPwd(direntry_t *entry)
149*d5c9a868SElliott Hughes {
150*d5c9a868SElliott Hughes 	size_t size;
151*d5c9a868SElliott Hughes 	char *ret;
152*d5c9a868SElliott Hughes 	char *end;
153*d5c9a868SElliott Hughes 	size_t buf_size;
154*d5c9a868SElliott Hughes 
155*d5c9a868SElliott Hughes 	size = getPathLen(entry);
156*d5c9a868SElliott Hughes 	buf_size = size*4+1;
157*d5c9a868SElliott Hughes 	ret = malloc(buf_size);
158*d5c9a868SElliott Hughes 	if(!ret)
159*d5c9a868SElliott Hughes 		return 0;
160*d5c9a868SElliott Hughes 	end = sprintPwd(entry, ret, &buf_size);
161*d5c9a868SElliott Hughes 	*end = '\0';
162*d5c9a868SElliott Hughes 	return ret;
163*d5c9a868SElliott Hughes }
164*d5c9a868SElliott Hughes 
isSubdirOf(Stream_t * inside,Stream_t * outside)165*d5c9a868SElliott Hughes int isSubdirOf(Stream_t *inside, Stream_t *outside)
166*d5c9a868SElliott Hughes {
167*d5c9a868SElliott Hughes 	while(1) {
168*d5c9a868SElliott Hughes 		if(inside == outside) /* both are the same */
169*d5c9a868SElliott Hughes 			return 1;
170*d5c9a868SElliott Hughes 		if(getDirentry(inside)->entry == -3) /* root directory */
171*d5c9a868SElliott Hughes 			return 0;
172*d5c9a868SElliott Hughes 		/* look further up */
173*d5c9a868SElliott Hughes 		inside = getDirentry(inside)->Dir;
174*d5c9a868SElliott Hughes 	}
175*d5c9a868SElliott Hughes }
176