@@ -34,6 +34,7 @@ use crate::state::issuer::{IssuerContext, IssuerState};
3434use  crate :: time:: { Time ,  TimeRange } ; 
3535
3636pub  const  ACCOUNT_URL_FILE :  & str  = "account.url" ; 
37+ pub  const  NGX_ACME_STATE_PREFIX :  Option < & str >  = get_state_prefix ( ) ; 
3738
3839const  ACCOUNT_KEY_FILE :  & str  = "account.key" ; 
3940const  NGX_ACME_DEFAULT_RESOLVER_TIMEOUT :  ngx_msec_t  = 30000 ; 
@@ -344,12 +345,10 @@ fn default_state_path(cf: &mut ngx_conf_t, name: &ngx_str_t) -> Result<ngx_str_t
344345    let  mut  path = Vec :: new_in ( cf. pool ( ) ) ; 
345346    let  reserve = "acme_" . len ( )  + name. len  + 1 ; 
346347
347-     if  let  Some ( p)  = core:: option_env!( "NGX_ACME_STATE_PREFIX" )  { 
348-         let  p = p. trim_end_matches ( '/' ) ; 
349-         path. try_reserve_exact ( p. len ( )  + reserve + 1 ) 
348+     if  let  Some ( p)  = NGX_ACME_STATE_PREFIX  { 
349+         path. try_reserve_exact ( p. len ( )  + reserve) 
350350            . map_err ( |_| AllocError ) ?; 
351351        path. extend ( p. as_bytes ( ) ) ; 
352-         path. push ( b'/' ) ; 
353352    } 
354353
355354    path. try_reserve_exact ( reserve) . map_err ( |_| AllocError ) ?; 
@@ -450,3 +449,32 @@ impl StateDir {
450449        Ok ( cert) 
451450    } 
452451} 
452+ 
453+ /// Returns NGX_ACME_STATE_PREFIX value with a trailing '/'. 
454+ const  fn  get_state_prefix ( )  -> Option < & ' static  str >  { 
455+     const  fn  trim_trailing_slashes ( x :  & str )  -> & str  { 
456+         let  mut  bytes = x. as_bytes ( ) ; 
457+         while  let  [ rest @ ..,  last]  = bytes { 
458+             if  * last == b'/'  { 
459+                 bytes = rest; 
460+             }  else  { 
461+                 break ; 
462+             } 
463+         } 
464+         // SAFETY: the transform above cannot produce an invalid UTF-8 sequence. 
465+         unsafe  {  core:: str:: from_utf8_unchecked ( bytes)  } 
466+     } 
467+ 
468+     const  VAL_0 :  Option < & str >  = core:: option_env!( "NGX_ACME_STATE_PREFIX" ) ; 
469+     if  VAL_0 . is_none ( )  { 
470+         return  None ; 
471+     } 
472+ 
473+     // Strip all the trailing slashes from the path. 
474+     const  VAL_1 :  & str  = match  VAL_0  { 
475+         Some ( x)  => trim_trailing_slashes ( x) , 
476+         None  => "" ,  // unreachable 
477+     } ; 
478+ 
479+     Some ( constcat:: concat!( VAL_1 ,  "/" ) ) 
480+ } 
0 commit comments