@@ -42,16 +42,6 @@ struct fsentry {
42
42
struct hashmap_entry ent ;
43
43
mode_t st_mode ;
44
44
ULONG reparse_tag ;
45
- /* Length of name. */
46
- unsigned short len ;
47
- /*
48
- * Name of the entry. For directory listings: relative path of the
49
- * directory, without trailing '/' (empty for cwd()). For file entries:
50
- * name of the file. Typically points to the end of the structure if
51
- * the fsentry is allocated on the heap (see fsentry_alloc), or to a
52
- * local variable if on the stack (see fsentry_init).
53
- */
54
- const char * name ;
55
45
/* Pointer to the directory listing, or NULL for the listing itself. */
56
46
struct fsentry * list ;
57
47
/* Pointer to the next file entry of the list. */
@@ -68,6 +58,22 @@ struct fsentry {
68
58
struct timespec st_ctim ;
69
59
} s ;
70
60
} u ;
61
+
62
+ /* Length of name. */
63
+ unsigned short len ;
64
+ /*
65
+ * Name of the entry. For directory listings: relative path of the
66
+ * directory, without trailing '/' (empty for cwd()). For file entries:
67
+ * name of the file. Typically points to the end of the structure if
68
+ * the fsentry is allocated on the heap (see fsentry_alloc), or to a
69
+ * local variable if on the stack (see fsentry_init).
70
+ */
71
+ struct dirent dirent ;
72
+ };
73
+
74
+ struct heap_fsentry {
75
+ struct fsentry ent ;
76
+ char dummy [MAX_LONG_PATH ];
71
77
};
72
78
73
79
/*
@@ -90,7 +96,7 @@ static int fsentry_cmp(void *unused_cmp_data,
90
96
/* if list parts are equal, compare len and name */
91
97
if (fse1 -> len != fse2 -> len )
92
98
return fse1 -> len - fse2 -> len ;
93
- return strnicmp (fse1 -> name , fse2 -> name , fse1 -> len );
99
+ return strnicmp (fse1 -> dirent . d_name , fse2 -> dirent . d_name , fse1 -> len );
94
100
}
95
101
96
102
/*
@@ -99,17 +105,21 @@ static int fsentry_cmp(void *unused_cmp_data,
99
105
static unsigned int fsentry_hash (const struct fsentry * fse )
100
106
{
101
107
unsigned int hash = fse -> list ? fse -> list -> ent .hash : 0 ;
102
- return hash ^ memihash (fse -> name , fse -> len );
108
+ return hash ^ memihash (fse -> dirent . d_name , fse -> len );
103
109
}
104
110
105
111
/*
106
112
* Initialize an fsentry structure for use by fsentry_hash and fsentry_cmp.
107
113
*/
108
114
static void fsentry_init (struct fsentry * fse , struct fsentry * list ,
109
- const char * name , size_t len )
115
+ const char * name , size_t len )
110
116
{
111
117
fse -> list = list ;
112
- fse -> name = name ;
118
+ if (len > MAX_LONG_PATH )
119
+ BUG ("Trying to allocate fsentry for long path '%.*s'" ,
120
+ (int )len , name );
121
+ memcpy (fse -> dirent .d_name , name , len );
122
+ fse -> dirent .d_name [len ] = 0 ;
113
123
fse -> len = len ;
114
124
hashmap_entry_init (& fse -> ent , fsentry_hash (fse ));
115
125
}
@@ -121,12 +131,10 @@ static struct fsentry *fsentry_alloc(struct fscache *cache, struct fsentry *list
121
131
size_t len )
122
132
{
123
133
/* overallocate fsentry and copy the name to the end */
124
- struct fsentry * fse = mem_pool_alloc (cache -> mem_pool , sizeof (struct fsentry ) + len + 1 );
125
- char * nm = ((char * ) fse ) + sizeof (struct fsentry );
126
- memcpy (nm , name , len );
127
- nm [len ] = 0 ;
134
+ struct fsentry * fse =
135
+ mem_pool_alloc (cache -> mem_pool , sizeof (struct fsentry ) + len + 1 );
128
136
/* init the rest of the structure */
129
- fsentry_init (fse , list , nm , len );
137
+ fsentry_init (fse , list , name , len );
130
138
fse -> next = NULL ;
131
139
fse -> u .refcnt = 1 ;
132
140
return fse ;
@@ -170,8 +178,9 @@ static int xwcstoutfn(char *utf, int utflen, const wchar_t *wcs, int wcslen)
170
178
/*
171
179
* Allocate and initialize an fsentry from a FILE_FULL_DIR_INFORMATION structure.
172
180
*/
173
- static struct fsentry * fseentry_create_entry (struct fscache * cache , struct fsentry * list ,
174
- PFILE_FULL_DIR_INFORMATION fdata )
181
+ static struct fsentry * fseentry_create_entry (struct fscache * cache ,
182
+ struct fsentry * list ,
183
+ PFILE_FULL_DIR_INFORMATION fdata )
175
184
{
176
185
char buf [MAX_PATH * 3 ];
177
186
int len ;
@@ -199,15 +208,19 @@ static struct fsentry *fseentry_create_entry(struct fscache *cache, struct fsent
199
208
is_inside_windows_container ()) {
200
209
size_t off = 0 ;
201
210
if (list ) {
202
- memcpy (buf , list -> name , list -> len );
211
+ memcpy (buf , list -> dirent . d_name , list -> len );
203
212
buf [list -> len ] = '/' ;
204
213
off = list -> len + 1 ;
205
214
}
206
- memcpy (buf + off , fse -> name , fse -> len );
215
+ memcpy (buf + off , fse -> dirent . d_name , fse -> len );
207
216
buf [off + fse -> len ] = '\0' ;
208
217
}
209
218
210
- fse -> st_mode = file_attr_to_st_mode (fdata -> FileAttributes , fdata -> EaSize , buf );
219
+ fse -> st_mode =
220
+ file_attr_to_st_mode (fdata -> FileAttributes , fdata -> EaSize , buf );
221
+ fse -> dirent .d_type = S_ISREG (fse -> st_mode ) ? DT_REG :
222
+ S_ISDIR (fse -> st_mode ) ? DT_DIR : DT_LNK ;
223
+
211
224
fse -> u .s .st_size = S_ISLNK (fse -> st_mode ) ? MAX_LONG_PATH :
212
225
fdata -> EndOfFile .LowPart | (((off_t )fdata -> EndOfFile .HighPart ) << 32 );
213
226
filetime_to_timespec ((FILETIME * )& (fdata -> LastAccessTime ), & (fse -> u .s .st_atim ));
@@ -222,7 +235,8 @@ static struct fsentry *fseentry_create_entry(struct fscache *cache, struct fsent
222
235
* Dir should not contain trailing '/'. Use an empty string for the current
223
236
* directory (not "."!).
224
237
*/
225
- static struct fsentry * fsentry_create_list (struct fscache * cache , const struct fsentry * dir ,
238
+ static struct fsentry * fsentry_create_list (struct fscache * cache ,
239
+ const struct fsentry * dir ,
226
240
int * dir_not_found )
227
241
{
228
242
wchar_t pattern [MAX_LONG_PATH ];
@@ -257,14 +271,15 @@ static struct fsentry *fsentry_create_list(struct fscache *cache, const struct f
257
271
err = GetLastError ();
258
272
* dir_not_found = 1 ; /* or empty directory */
259
273
errno = (err == ERROR_DIRECTORY ) ? ENOTDIR : err_win_to_posix (err );
260
- trace_printf_key (& trace_fscache , "fscache: error(%d) '%.* s'\n" ,
261
- errno , dir -> len , dir -> name );
274
+ trace_printf_key (& trace_fscache , "fscache: error(%d) '%s'\n" ,
275
+ errno , dir -> dirent . d_name );
262
276
return NULL ;
263
277
}
264
278
265
279
/* allocate object to hold directory listing */
266
- list = fsentry_alloc (cache , NULL , dir -> name , dir -> len );
280
+ list = fsentry_alloc (cache , NULL , dir -> dirent . d_name , dir -> len );
267
281
list -> st_mode = S_IFDIR ;
282
+ list -> dirent .d_type = DT_DIR ;
268
283
269
284
/* walk directory and build linked list of fsentry structures */
270
285
phead = & list -> next ;
@@ -312,8 +327,9 @@ static struct fsentry *fsentry_create_list(struct fscache *cache, const struct f
312
327
return list ;
313
328
314
329
Error :
315
- trace_printf_key (& trace_fscache , "fscache: status(%ld) unable to query directory contents '%.*s'\n" ,
316
- status , dir -> len , dir -> name );
330
+ trace_printf_key (& trace_fscache , "fscache: status(%ld) unable to query "
331
+ "directory contents '%s'\n" ,
332
+ status , dir -> dirent .d_name );
317
333
CloseHandle (h );
318
334
fsentry_release (list );
319
335
return NULL ;
@@ -553,7 +569,8 @@ void fscache_flush(void)
553
569
int fscache_lstat (const char * filename , struct stat * st )
554
570
{
555
571
int dirlen , base , len ;
556
- struct fsentry key [2 ], * fse ;
572
+ struct heap_fsentry key [2 ];
573
+ struct fsentry * fse ;
557
574
struct fscache * cache = fscache_getcache ();
558
575
559
576
if (!cache || !do_fscache_enabled (cache , filename ))
@@ -570,9 +587,9 @@ int fscache_lstat(const char *filename, struct stat *st)
570
587
dirlen = base ? base - 1 : 0 ;
571
588
572
589
/* lookup entry for path + name in cache */
573
- fsentry_init (key , NULL , filename , dirlen );
574
- fsentry_init (key + 1 , key , filename + base , len - base );
575
- fse = fscache_get (cache , key + 1 );
590
+ fsentry_init (& key [ 0 ]. ent , NULL , filename , dirlen );
591
+ fsentry_init (& key [ 1 ]. ent , & key [ 0 ]. ent , filename + base , len - base );
592
+ fse = fscache_get (cache , & key [ 1 ]. ent );
576
593
if (!fse )
577
594
return -1 ;
578
595
@@ -629,7 +646,7 @@ int fscache_is_mount_point(struct strbuf *path)
629
646
typedef struct fscache_DIR {
630
647
struct DIR base_dir ; /* extend base struct DIR */
631
648
struct fsentry * pfsentry ;
632
- struct dirent dirent ;
649
+ struct dirent * dirent ;
633
650
} fscache_DIR ;
634
651
635
652
/*
@@ -642,10 +659,8 @@ static struct dirent *fscache_readdir(DIR *base_dir)
642
659
if (!next )
643
660
return NULL ;
644
661
dir -> pfsentry = next ;
645
- dir -> dirent .d_type = S_ISREG (next -> st_mode ) ? DT_REG :
646
- S_ISDIR (next -> st_mode ) ? DT_DIR : DT_LNK ;
647
- dir -> dirent .d_name = (char * ) next -> name ;
648
- return & (dir -> dirent );
662
+ dir -> dirent = & next -> dirent ;
663
+ return dir -> dirent ;
649
664
}
650
665
651
666
/*
@@ -665,7 +680,8 @@ static int fscache_closedir(DIR *base_dir)
665
680
*/
666
681
DIR * fscache_opendir (const char * dirname )
667
682
{
668
- struct fsentry key , * list ;
683
+ struct heap_fsentry key ;
684
+ struct fsentry * list ;
669
685
fscache_DIR * dir ;
670
686
int len ;
671
687
struct fscache * cache = fscache_getcache ();
@@ -681,8 +697,8 @@ DIR *fscache_opendir(const char *dirname)
681
697
len -- ;
682
698
683
699
/* get directory listing from cache */
684
- fsentry_init (& key , NULL , dirname , len );
685
- list = fscache_get (cache , & key );
700
+ fsentry_init (& key . ent , NULL , dirname , len );
701
+ list = fscache_get (cache , & key . ent );
686
702
if (!list )
687
703
return NULL ;
688
704
0 commit comments