@@ -2283,3 +2283,222 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra
2283
2283
strbuf_release (& wd .sb_stat );
2284
2284
strbuf_release (& wd .sb_sha1 );
2285
2285
}
2286
+
2287
+ static void free_untracked (struct untracked_cache_dir * ucd )
2288
+ {
2289
+ int i ;
2290
+ if (!ucd )
2291
+ return ;
2292
+ for (i = 0 ; i < ucd -> dirs_nr ; i ++ )
2293
+ free_untracked (ucd -> dirs [i ]);
2294
+ for (i = 0 ; i < ucd -> untracked_nr ; i ++ )
2295
+ free (ucd -> untracked [i ]);
2296
+ free (ucd -> untracked );
2297
+ free (ucd -> dirs );
2298
+ free (ucd );
2299
+ }
2300
+
2301
+ void free_untracked_cache (struct untracked_cache * uc )
2302
+ {
2303
+ if (uc )
2304
+ free_untracked (uc -> root );
2305
+ free (uc );
2306
+ }
2307
+
2308
+ struct read_data {
2309
+ int index ;
2310
+ struct untracked_cache_dir * * ucd ;
2311
+ struct ewah_bitmap * check_only ;
2312
+ struct ewah_bitmap * valid ;
2313
+ struct ewah_bitmap * sha1_valid ;
2314
+ const unsigned char * data ;
2315
+ const unsigned char * end ;
2316
+ };
2317
+
2318
+ static void stat_data_from_disk (struct stat_data * to , const struct stat_data * from )
2319
+ {
2320
+ to -> sd_ctime .sec = get_be32 (& from -> sd_ctime .sec );
2321
+ to -> sd_ctime .nsec = get_be32 (& from -> sd_ctime .nsec );
2322
+ to -> sd_mtime .sec = get_be32 (& from -> sd_mtime .sec );
2323
+ to -> sd_mtime .nsec = get_be32 (& from -> sd_mtime .nsec );
2324
+ to -> sd_dev = get_be32 (& from -> sd_dev );
2325
+ to -> sd_ino = get_be32 (& from -> sd_ino );
2326
+ to -> sd_uid = get_be32 (& from -> sd_uid );
2327
+ to -> sd_gid = get_be32 (& from -> sd_gid );
2328
+ to -> sd_size = get_be32 (& from -> sd_size );
2329
+ }
2330
+
2331
+ static int read_one_dir (struct untracked_cache_dir * * untracked_ ,
2332
+ struct read_data * rd )
2333
+ {
2334
+ struct untracked_cache_dir ud , * untracked ;
2335
+ const unsigned char * next , * data = rd -> data , * end = rd -> end ;
2336
+ unsigned int value ;
2337
+ int i , len ;
2338
+
2339
+ memset (& ud , 0 , sizeof (ud ));
2340
+
2341
+ next = data ;
2342
+ value = decode_varint (& next );
2343
+ if (next > end )
2344
+ return -1 ;
2345
+ ud .recurse = 1 ;
2346
+ ud .untracked_alloc = value ;
2347
+ ud .untracked_nr = value ;
2348
+ if (ud .untracked_nr )
2349
+ ud .untracked = xmalloc (sizeof (* ud .untracked ) * ud .untracked_nr );
2350
+ data = next ;
2351
+
2352
+ next = data ;
2353
+ ud .dirs_alloc = ud .dirs_nr = decode_varint (& next );
2354
+ if (next > end )
2355
+ return -1 ;
2356
+ ud .dirs = xmalloc (sizeof (* ud .dirs ) * ud .dirs_nr );
2357
+ data = next ;
2358
+
2359
+ len = strlen ((const char * )data );
2360
+ next = data + len + 1 ;
2361
+ if (next > rd -> end )
2362
+ return -1 ;
2363
+ * untracked_ = untracked = xmalloc (sizeof (* untracked ) + len );
2364
+ memcpy (untracked , & ud , sizeof (ud ));
2365
+ memcpy (untracked -> name , data , len + 1 );
2366
+ data = next ;
2367
+
2368
+ for (i = 0 ; i < untracked -> untracked_nr ; i ++ ) {
2369
+ len = strlen ((const char * )data );
2370
+ next = data + len + 1 ;
2371
+ if (next > rd -> end )
2372
+ return -1 ;
2373
+ untracked -> untracked [i ] = xstrdup ((const char * )data );
2374
+ data = next ;
2375
+ }
2376
+
2377
+ rd -> ucd [rd -> index ++ ] = untracked ;
2378
+ rd -> data = data ;
2379
+
2380
+ for (i = 0 ; i < untracked -> dirs_nr ; i ++ ) {
2381
+ len = read_one_dir (untracked -> dirs + i , rd );
2382
+ if (len < 0 )
2383
+ return -1 ;
2384
+ }
2385
+ return 0 ;
2386
+ }
2387
+
2388
+ static void set_check_only (size_t pos , void * cb )
2389
+ {
2390
+ struct read_data * rd = cb ;
2391
+ struct untracked_cache_dir * ud = rd -> ucd [pos ];
2392
+ ud -> check_only = 1 ;
2393
+ }
2394
+
2395
+ static void read_stat (size_t pos , void * cb )
2396
+ {
2397
+ struct read_data * rd = cb ;
2398
+ struct untracked_cache_dir * ud = rd -> ucd [pos ];
2399
+ if (rd -> data + sizeof (struct stat_data ) > rd -> end ) {
2400
+ rd -> data = rd -> end + 1 ;
2401
+ return ;
2402
+ }
2403
+ stat_data_from_disk (& ud -> stat_data , (struct stat_data * )rd -> data );
2404
+ rd -> data += sizeof (struct stat_data );
2405
+ ud -> valid = 1 ;
2406
+ }
2407
+
2408
+ static void read_sha1 (size_t pos , void * cb )
2409
+ {
2410
+ struct read_data * rd = cb ;
2411
+ struct untracked_cache_dir * ud = rd -> ucd [pos ];
2412
+ if (rd -> data + 20 > rd -> end ) {
2413
+ rd -> data = rd -> end + 1 ;
2414
+ return ;
2415
+ }
2416
+ hashcpy (ud -> exclude_sha1 , rd -> data );
2417
+ rd -> data += 20 ;
2418
+ }
2419
+
2420
+ static void load_sha1_stat (struct sha1_stat * sha1_stat ,
2421
+ const struct stat_data * stat ,
2422
+ const unsigned char * sha1 )
2423
+ {
2424
+ stat_data_from_disk (& sha1_stat -> stat , stat );
2425
+ hashcpy (sha1_stat -> sha1 , sha1 );
2426
+ sha1_stat -> valid = 1 ;
2427
+ }
2428
+
2429
+ struct untracked_cache * read_untracked_extension (const void * data , unsigned long sz )
2430
+ {
2431
+ const struct ondisk_untracked_cache * ouc ;
2432
+ struct untracked_cache * uc ;
2433
+ struct read_data rd ;
2434
+ const unsigned char * next = data , * end = (const unsigned char * )data + sz ;
2435
+ int len ;
2436
+
2437
+ if (sz <= 1 || end [-1 ] != '\0' )
2438
+ return NULL ;
2439
+ end -- ;
2440
+
2441
+ ouc = (const struct ondisk_untracked_cache * )next ;
2442
+ if (next + ouc_size (0 ) > end )
2443
+ return NULL ;
2444
+
2445
+ uc = xcalloc (1 , sizeof (* uc ));
2446
+ load_sha1_stat (& uc -> ss_info_exclude , & ouc -> info_exclude_stat ,
2447
+ ouc -> info_exclude_sha1 );
2448
+ load_sha1_stat (& uc -> ss_excludes_file , & ouc -> excludes_file_stat ,
2449
+ ouc -> excludes_file_sha1 );
2450
+ uc -> dir_flags = get_be32 (& ouc -> dir_flags );
2451
+ uc -> exclude_per_dir = xstrdup (ouc -> exclude_per_dir );
2452
+ /* NUL after exclude_per_dir is covered by sizeof(*ouc) */
2453
+ next += ouc_size (strlen (ouc -> exclude_per_dir ));
2454
+ if (next >= end )
2455
+ goto done2 ;
2456
+
2457
+ len = decode_varint (& next );
2458
+ if (next > end || len == 0 )
2459
+ goto done2 ;
2460
+
2461
+ rd .valid = ewah_new ();
2462
+ rd .check_only = ewah_new ();
2463
+ rd .sha1_valid = ewah_new ();
2464
+ rd .data = next ;
2465
+ rd .end = end ;
2466
+ rd .index = 0 ;
2467
+ rd .ucd = xmalloc (sizeof (* rd .ucd ) * len );
2468
+
2469
+ if (read_one_dir (& uc -> root , & rd ) || rd .index != len )
2470
+ goto done ;
2471
+
2472
+ next = rd .data ;
2473
+ len = ewah_read_mmap (rd .valid , next , end - next );
2474
+ if (len < 0 )
2475
+ goto done ;
2476
+
2477
+ next += len ;
2478
+ len = ewah_read_mmap (rd .check_only , next , end - next );
2479
+ if (len < 0 )
2480
+ goto done ;
2481
+
2482
+ next += len ;
2483
+ len = ewah_read_mmap (rd .sha1_valid , next , end - next );
2484
+ if (len < 0 )
2485
+ goto done ;
2486
+
2487
+ ewah_each_bit (rd .check_only , set_check_only , & rd );
2488
+ rd .data = next + len ;
2489
+ ewah_each_bit (rd .valid , read_stat , & rd );
2490
+ ewah_each_bit (rd .sha1_valid , read_sha1 , & rd );
2491
+ next = rd .data ;
2492
+
2493
+ done :
2494
+ free (rd .ucd );
2495
+ ewah_free (rd .valid );
2496
+ ewah_free (rd .check_only );
2497
+ ewah_free (rd .sha1_valid );
2498
+ done2 :
2499
+ if (next != end ) {
2500
+ free_untracked_cache (uc );
2501
+ uc = NULL ;
2502
+ }
2503
+ return uc ;
2504
+ }
0 commit comments