@@ -2283,3 +2283,222 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra
22832283 strbuf_release (& wd .sb_stat );
22842284 strbuf_release (& wd .sb_sha1 );
22852285}
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