@@ -69,13 +69,31 @@ fn download_asset(client: &Client, asset: &Asset) -> Result<(), Box<dyn std::err
6969 . timeout ( Duration :: from_secs ( 30 ) )
7070 . send ( ) ?;
7171
72+ // Check if response is successful
73+ if !resp. status ( ) . is_success ( ) {
74+ return Err ( format ! ( "HTTP error: {}" , resp. status( ) ) . into ( ) ) ;
75+ }
76+
7277 // Create output path and temporary file for safe downloading
7378 let mut out_path = PathBuf :: from ( DEST_DIR ) ;
7479 out_path. push ( & asset. name ) ;
7580
81+ // Ensure parent directory exists
82+ if let Some ( parent) = out_path. parent ( ) {
83+ fs:: create_dir_all ( parent) ?;
84+ }
85+
7686 let tmp_path = out_path. with_extension ( "tmp" ) ;
7787 let mut file = fs:: File :: create ( & tmp_path) ?;
7888 copy ( & mut resp, & mut file) ?;
89+
90+ // Verify file was written and has content
91+ let metadata = fs:: metadata ( & tmp_path) ?;
92+ if metadata. len ( ) == 0 {
93+ fs:: remove_file ( & tmp_path) ?;
94+ return Err ( "Downloaded file is empty" . into ( ) ) ;
95+ }
96+
7997 // Atomically rename temporary file to final destination
8098 fs:: rename ( tmp_path, & out_path) ?;
8199
@@ -89,11 +107,28 @@ fn delegate_to_real_loader(lua: State) -> i32 {
89107 let suffix = get_platform_suffix ( ) ;
90108 let lib_name = format ! ( "{}/gmsv_gmod_integration_{}.dll" , DEST_DIR , suffix) ;
91109
92- let lib = libloading:: Library :: new ( & lib_name)
93- . unwrap_or_else ( |_| panic ! ( "Cannot load real integration: {}" , lib_name) ) ;
110+ // Check if file exists before trying to load
111+ if !std:: path:: Path :: new ( & lib_name) . exists ( ) {
112+ print_log ( & format ! ( "Real integration file not found: {}" , lib_name) ) ;
113+ return 1 ;
114+ }
115+
116+ let lib = match libloading:: Library :: new ( & lib_name) {
117+ Ok ( lib) => lib,
118+ Err ( e) => {
119+ print_log ( & format ! ( "Failed to load real integration: {}" , e) ) ;
120+ return 1 ;
121+ }
122+ } ;
123+
94124 // Get the gmod13_open function from the real integration
95- let func: libloading:: Symbol < unsafe extern "C" fn ( State ) -> i32 > =
96- lib. get ( b"gmod13_open" ) . expect ( "symbol not found" ) ;
125+ let func: libloading:: Symbol < unsafe extern "C" fn ( State ) -> i32 > = match lib. get ( b"gmod13_open" ) {
126+ Ok ( func) => func,
127+ Err ( e) => {
128+ print_log ( & format ! ( "Failed to find gmod13_open symbol: {}" , e) ) ;
129+ return 1 ;
130+ }
131+ } ;
97132
98133 print_log ( "Delegated to real integration" ) ;
99134 func ( lua)
@@ -107,7 +142,7 @@ fn gmod13_open(lua: State) -> i32 {
107142 // Ensure destination directory exists
108143 if let Err ( e) = fs:: create_dir_all ( DEST_DIR ) {
109144 print_log ( & format ! ( "Failed to create directory: {}" , e) ) ;
110- return delegate_to_real_loader ( lua ) ;
145+ return 1 ; // Don't delegate if we can't even create directories
111146 }
112147
113148 let mut version_cache = load_loader_version_cache ( ) ;
@@ -122,17 +157,33 @@ fn gmod13_open(lua: State) -> i32 {
122157 let release: Release = match client
123158 . get ( API_LATEST )
124159 . header ( "User-Agent" , "Gmod-Auto-Loader" )
160+ . timeout ( Duration :: from_secs ( 30 ) )
125161 . send ( )
126162 . and_then ( |r| r. error_for_status ( ) )
127163 . and_then ( |r| r. json ( ) )
128164 {
129165 Ok ( r) => r,
130166 Err ( e) => {
131167 print_log ( & format ! ( "Error fetching release: {}" , e) ) ;
132- return delegate_to_real_loader ( lua) ;
168+ // If file exists, still try to delegate
169+ if file_exists {
170+ return delegate_to_real_loader ( lua) ;
171+ }
172+ return 1 ;
133173 }
134174 } ;
135175
176+ // Validate release data
177+ if release. tag_name . is_empty ( ) {
178+ print_log ( "Invalid release: empty tag name" ) ;
179+ return delegate_to_real_loader ( lua) ;
180+ }
181+
182+ if release. assets . is_empty ( ) {
183+ print_log ( "No assets found in release" ) ;
184+ return delegate_to_real_loader ( lua) ;
185+ }
186+
136187 // Skip update if version matches and file exists
137188 if let Some ( current_version) = & version_cache. gmod_integration_loader {
138189 if current_version == & release. tag_name && file_exists {
@@ -151,20 +202,34 @@ fn gmod13_open(lua: State) -> i32 {
151202
152203 // Download the appropriate binary for current platform
153204 let target_asset = format ! ( "gmsv_gmod_integration_{}.dll" , suffix) ;
205+ let mut found_asset = false ;
154206
155207 for asset in & release. assets {
156208 if asset. name == target_asset {
209+ found_asset = true ;
157210 if let Err ( e) = download_asset ( & client, asset) {
158211 print_log ( & format ! ( "Failed to download {}: {}" , asset. name, e) ) ;
212+ // Clean up any partial download
213+ let partial_path = PathBuf :: from ( DEST_DIR ) . join ( & asset. name ) ;
214+ let _ = fs:: remove_file ( partial_path) ;
159215 return delegate_to_real_loader ( lua) ;
160216 }
161217 break ;
162218 }
163219 }
164220
221+ if !found_asset {
222+ print_log ( & format ! ( "No matching asset found for platform: {}" , suffix) ) ;
223+ return delegate_to_real_loader ( lua) ;
224+ }
225+
165226 // Update version cache with new version
166227 version_cache. gmod_integration_loader = Some ( release. tag_name ) ;
167- save_loader_version_cache ( & version_cache) ;
228+ if let Err ( e) = serde_json:: to_string_pretty ( & version_cache)
229+ . map_err ( |e| e. into ( ) )
230+ . and_then ( |content| fs:: write ( VERSION_FILE , content) . map_err ( |e| e. into ( ) ) ) {
231+ print_log ( & format ! ( "Failed to save version cache: {}" , e) ) ;
232+ }
168233
169234 print_log ( "Update completed, delegating to real integration" ) ;
170235 delegate_to_real_loader ( lua)
@@ -177,10 +242,28 @@ fn gmod13_close(lua: State) -> i32 {
177242 let suffix = get_platform_suffix ( ) ;
178243 let lib_name = format ! ( "{}/gmsv_gmod_integration_{}.dll" , DEST_DIR , suffix) ;
179244
180- let lib = libloading:: Library :: new ( & lib_name)
181- . unwrap_or_else ( |_| panic ! ( "Cannot load real integration: {}" , lib_name) ) ;
182- let func: libloading:: Symbol < unsafe extern "C" fn ( State ) -> i32 > =
183- lib. get ( b"gmod13_close" ) . expect ( "symbol not found" ) ;
245+ // Check if file exists before trying to load
246+ if !std:: path:: Path :: new ( & lib_name) . exists ( ) {
247+ print_log ( & format ! ( "Real integration file not found during close: {}" , lib_name) ) ;
248+ return 0 ; // Don't fail the close operation
249+ }
250+
251+ let lib = match libloading:: Library :: new ( & lib_name) {
252+ Ok ( lib) => lib,
253+ Err ( e) => {
254+ print_log ( & format ! ( "Failed to load real integration during close: {}" , e) ) ;
255+ return 0 ; // Don't fail the close operation
256+ }
257+ } ;
258+
259+ let func: libloading:: Symbol < unsafe extern "C" fn ( State ) -> i32 > = match lib. get ( b"gmod13_close" ) {
260+ Ok ( func) => func,
261+ Err ( e) => {
262+ print_log ( & format ! ( "Failed to find gmod13_close symbol: {}" , e) ) ;
263+ return 0 ; // Don't fail the close operation
264+ }
265+ } ;
266+
184267 func ( lua)
185268 }
186269}
0 commit comments