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