44// file that was distributed with this source code.
55
66#[ cfg( target_os = "linux" ) ]
7- use chrono:: Datelike ;
7+ use chrono:: { Datelike , Local } ;
88use clap:: crate_version;
99use clap:: { Arg , ArgAction , Command } ;
1010#[ cfg( target_os = "linux" ) ]
@@ -134,7 +134,7 @@ fn format_time(time: String) -> Result<String, chrono::format::ParseError> {
134134 t = t. drain ( ..time_offset) . collect ( ) ;
135135 }
136136 // If login time day is not current day, format like Sat16, or Fri06
137- let current_dt = chrono :: Local :: now ( ) . fixed_offset ( ) ;
137+ let current_dt = Local :: now ( ) . fixed_offset ( ) ;
138138 let dt = chrono:: DateTime :: parse_from_str ( & t, "%Y-%m-%d %H:%M:%S%.f %:z" ) ?;
139139
140140 if current_dt. day ( ) == dt. day ( ) {
@@ -182,6 +182,17 @@ fn fetch_user_info() -> Result<Vec<UserInfo>, std::io::Error> {
182182 Ok ( user_info_list)
183183}
184184
185+ #[ cfg( target_os = "linux" ) ]
186+ fn get_uptime_container ( ) -> UResult < i64 > {
187+ let proc_file = fs:: read_to_string ( "/proc/1/stat" ) ?;
188+ let proc_stat: Vec < & str > = proc_file. split_whitespace ( ) . collect ( ) ;
189+ let start_time_str = proc_stat. get ( 21 ) . ok_or ( UptimeError :: SystemUptime ) ?;
190+ let start_time: i64 = start_time_str
191+ . parse ( )
192+ . map_err ( |_| UptimeError :: SystemUptime ) ?;
193+ Ok ( get_uptime ( None ) ? + start_time / get_clock_tick ( ) )
194+ }
195+
185196pub fn format_uptime_procps ( up_secs : i64 ) -> UResult < String > {
186197 if up_secs < 0 {
187198 Err ( UptimeError :: SystemUptime ) ?;
@@ -208,9 +219,25 @@ pub fn get_formatted_uptime_procps() -> UResult<String> {
208219 Ok ( format ! ( "up {time_str}" ) )
209220}
210221
211- fn print_uptime ( ) {
222+ #[ cfg( target_os = "linux" ) ]
223+ #[ inline]
224+ fn get_formatted_uptime_container_procps ( ) -> UResult < String > {
225+ let time_str = format_uptime_procps ( get_uptime_container ( ) ?) ?;
226+ Ok ( format ! ( "up {time_str}" ) )
227+ }
228+
229+ #[ allow( unused_variables) ]
230+ fn print_uptime ( from_container : bool ) {
212231 print ! ( " {} " , get_formatted_time( ) ) ;
213- if let Ok ( uptime) = get_formatted_uptime_procps ( ) {
232+ #[ cfg( target_os = "linux" ) ]
233+ let uptime = if from_container {
234+ get_formatted_uptime_container_procps ( )
235+ } else {
236+ get_formatted_uptime_procps ( )
237+ } ;
238+ #[ cfg( not( target_os = "linux" ) ) ]
239+ let uptime = get_formatted_uptime_procps ( ) ;
240+ if let Ok ( uptime) = uptime {
214241 print ! ( "{uptime}, " ) ;
215242 } else {
216243 print ! ( "up ???? days ??:??, " ) ;
@@ -235,11 +262,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
235262 let no_header = matches. get_flag ( "no-header" ) ;
236263 let short = matches. get_flag ( "short" ) ;
237264 let old_style = matches. get_flag ( "old-style" ) ;
265+ let container = matches. get_flag ( "container" ) ;
238266
239267 match fetch_user_info ( ) {
240268 Ok ( user_info) => {
241269 if !no_header {
242- print_uptime ( ) ;
270+ print_uptime ( container ) ;
243271 if short {
244272 println ! ( "{:<9}{:<9}{:<7}{:<}" , "USER" , "TTY" , "IDLE" , "WHAT" ) ;
245273 } else {
@@ -294,6 +322,13 @@ pub fn uu_app() -> Command {
294322 . help ( "Print help information" )
295323 . action ( ArgAction :: Help ) ,
296324 )
325+ . arg (
326+ Arg :: new ( "container" )
327+ . short ( 'c' )
328+ . long ( "container" )
329+ . help ( "show the container uptime instead of system uptime in the header" )
330+ . action ( ArgAction :: SetTrue ) ,
331+ )
297332 . arg (
298333 Arg :: new ( "no-header" )
299334 . short ( 'h' )
0 commit comments