LCOV - code coverage report
Current view: top level - openssh-6.6p1 - progressmeter.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 0 123 0.0 %
Date: 2014-08-01 Functions: 0 9 0.0 %
Branches: 0 62 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* $OpenBSD: progressmeter.c,v 1.40 2013/09/19 00:24:52 djm Exp $ */
       2                 :            : /*
       3                 :            :  * Copyright (c) 2003 Nils Nordman.  All rights reserved.
       4                 :            :  *
       5                 :            :  * Redistribution and use in source and binary forms, with or without
       6                 :            :  * modification, are permitted provided that the following conditions
       7                 :            :  * are met:
       8                 :            :  * 1. Redistributions of source code must retain the above copyright
       9                 :            :  *    notice, this list of conditions and the following disclaimer.
      10                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      11                 :            :  *    notice, this list of conditions and the following disclaimer in the
      12                 :            :  *    documentation and/or other materials provided with the distribution.
      13                 :            :  *
      14                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      15                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      16                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      17                 :            :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      18                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      19                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      20                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      21                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      22                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      23                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      24                 :            :  */
      25                 :            : 
      26                 :            : #include "includes.h"
      27                 :            : 
      28                 :            : #include <sys/types.h>
      29                 :            : #include <sys/ioctl.h>
      30                 :            : #include <sys/uio.h>
      31                 :            : 
      32                 :            : #include <errno.h>
      33                 :            : #include <signal.h>
      34                 :            : #include <stdio.h>
      35                 :            : #include <string.h>
      36                 :            : #include <time.h>
      37                 :            : #include <unistd.h>
      38                 :            : 
      39                 :            : #include "progressmeter.h"
      40                 :            : #include "atomicio.h"
      41                 :            : #include "misc.h"
      42                 :            : 
      43                 :            : #define DEFAULT_WINSIZE 80
      44                 :            : #define MAX_WINSIZE 512
      45                 :            : #define PADDING 1               /* padding between the progress indicators */
      46                 :            : #define UPDATE_INTERVAL 1       /* update the progress meter every second */
      47                 :            : #define STALL_TIME 5            /* we're stalled after this many seconds */
      48                 :            : 
      49                 :            : /* determines whether we can output to the terminal */
      50                 :            : static int can_output(void);
      51                 :            : 
      52                 :            : /* formats and inserts the specified size into the given buffer */
      53                 :            : static void format_size(char *, int, off_t);
      54                 :            : static void format_rate(char *, int, off_t);
      55                 :            : 
      56                 :            : /* window resizing */
      57                 :            : static void sig_winch(int);
      58                 :            : static void setscreensize(void);
      59                 :            : 
      60                 :            : /* updates the progressmeter to reflect the current state of the transfer */
      61                 :            : void refresh_progress_meter(void);
      62                 :            : 
      63                 :            : /* signal handler for updating the progress meter */
      64                 :            : static void update_progress_meter(int);
      65                 :            : 
      66                 :            : static time_t start;            /* start progress */
      67                 :            : static time_t last_update;      /* last progress update */
      68                 :            : static char *file;              /* name of the file being transferred */
      69                 :            : static off_t start_pos;         /* initial position of transfer */
      70                 :            : static off_t end_pos;           /* ending position of transfer */
      71                 :            : static off_t cur_pos;           /* transfer position as of last refresh */
      72                 :            : static volatile off_t *counter; /* progress counter */
      73                 :            : static long stalled;            /* how long we have been stalled */
      74                 :            : static int bytes_per_second;    /* current speed in bytes per second */
      75                 :            : static int win_size;            /* terminal window size */
      76                 :            : static volatile sig_atomic_t win_resized; /* for window resizing */
      77                 :            : 
      78                 :            : /* units for format_size */
      79                 :            : static const char unit[] = " KMGT";
      80                 :            : 
      81                 :            : static int
      82                 :          0 : can_output(void)
      83                 :            : {
      84                 :          0 :         return (getpgrp() == tcgetpgrp(STDOUT_FILENO));
      85                 :            : }
      86                 :            : 
      87                 :            : static void
      88                 :          0 : format_rate(char *buf, int size, off_t bytes)
      89                 :            : {
      90                 :            :         int i;
      91                 :            : 
      92                 :          0 :         bytes *= 100;
      93 [ #  # ][ #  # ]:          0 :         for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++)
      94                 :          0 :                 bytes = (bytes + 512) / 1024;
      95         [ #  # ]:          0 :         if (i == 0) {
      96                 :          0 :                 i++;
      97                 :          0 :                 bytes = (bytes + 512) / 1024;
      98                 :            :         }
      99         [ #  # ]:          0 :         snprintf(buf, size, "%3lld.%1lld%c%s",
     100                 :            :             (long long) (bytes + 5) / 100,
     101                 :          0 :             (long long) (bytes + 5) / 10 % 10,
     102                 :          0 :             unit[i],
     103                 :            :             i ? "B" : " ");
     104                 :          0 : }
     105                 :            : 
     106                 :            : static void
     107                 :          0 : format_size(char *buf, int size, off_t bytes)
     108                 :            : {
     109                 :            :         int i;
     110                 :            : 
     111 [ #  # ][ #  # ]:          0 :         for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++)
     112                 :          0 :                 bytes = (bytes + 512) / 1024;
     113         [ #  # ]:          0 :         snprintf(buf, size, "%4lld%c%s",
     114                 :            :             (long long) bytes,
     115                 :          0 :             unit[i],
     116                 :            :             i ? "B" : " ");
     117                 :          0 : }
     118                 :            : 
     119                 :            : void
     120                 :          0 : refresh_progress_meter(void)
     121                 :            : {
     122                 :            :         char buf[MAX_WINSIZE + 1];
     123                 :            :         time_t now;
     124                 :            :         off_t transferred;
     125                 :            :         double elapsed;
     126                 :            :         int percent;
     127                 :            :         off_t bytes_left;
     128                 :            :         int cur_speed;
     129                 :            :         int hours, minutes, seconds;
     130                 :            :         int i, len;
     131                 :            :         int file_len;
     132                 :            : 
     133         [ #  # ]:          0 :         transferred = *counter - (cur_pos ? cur_pos : start_pos);
     134                 :          0 :         cur_pos = *counter;
     135                 :          0 :         now = monotime();
     136                 :          0 :         bytes_left = end_pos - cur_pos;
     137                 :            : 
     138         [ #  # ]:          0 :         if (bytes_left > 0)
     139                 :          0 :                 elapsed = now - last_update;
     140                 :            :         else {
     141                 :          0 :                 elapsed = now - start;
     142                 :            :                 /* Calculate true total speed when done */
     143                 :          0 :                 transferred = end_pos - start_pos;
     144                 :          0 :                 bytes_per_second = 0;
     145                 :            :         }
     146                 :            : 
     147                 :            :         /* calculate speed */
     148         [ #  # ]:          0 :         if (elapsed != 0)
     149                 :          0 :                 cur_speed = (transferred / elapsed);
     150                 :            :         else
     151                 :          0 :                 cur_speed = transferred;
     152                 :            : 
     153                 :            : #define AGE_FACTOR 0.9
     154         [ #  # ]:          0 :         if (bytes_per_second != 0) {
     155                 :          0 :                 bytes_per_second = (bytes_per_second * AGE_FACTOR) +
     156                 :          0 :                     (cur_speed * (1.0 - AGE_FACTOR));
     157                 :            :         } else
     158                 :          0 :                 bytes_per_second = cur_speed;
     159                 :            : 
     160                 :            :         /* filename */
     161                 :          0 :         buf[0] = '\0';
     162                 :          0 :         file_len = win_size - 35;
     163         [ #  # ]:          0 :         if (file_len > 0) {
     164                 :          0 :                 len = snprintf(buf, file_len + 1, "\r%s", file);
     165         [ #  # ]:          0 :                 if (len < 0)
     166                 :          0 :                         len = 0;
     167         [ #  # ]:          0 :                 if (len >= file_len + 1)
     168                 :          0 :                         len = file_len;
     169         [ #  # ]:          0 :                 for (i = len; i < file_len; i++)
     170                 :          0 :                         buf[i] = ' ';
     171                 :          0 :                 buf[file_len] = '\0';
     172                 :            :         }
     173                 :            : 
     174                 :            :         /* percent of transfer done */
     175         [ #  # ]:          0 :         if (end_pos != 0)
     176                 :          0 :                 percent = ((float)cur_pos / end_pos) * 100;
     177                 :            :         else
     178                 :            :                 percent = 100;
     179                 :          0 :         snprintf(buf + strlen(buf), win_size - strlen(buf),
     180                 :            :             " %3d%% ", percent);
     181                 :            : 
     182                 :            :         /* amount transferred */
     183                 :          0 :         format_size(buf + strlen(buf), win_size - strlen(buf),
     184                 :            :             cur_pos);
     185                 :          0 :         strlcat(buf, " ", win_size);
     186                 :            : 
     187                 :            :         /* bandwidth usage */
     188                 :          0 :         format_rate(buf + strlen(buf), win_size - strlen(buf),
     189                 :            :             (off_t)bytes_per_second);
     190                 :          0 :         strlcat(buf, "/s ", win_size);
     191                 :            : 
     192                 :            :         /* ETA */
     193         [ #  # ]:          0 :         if (!transferred)
     194                 :          0 :                 stalled += elapsed;
     195                 :            :         else
     196                 :          0 :                 stalled = 0;
     197                 :            : 
     198         [ #  # ]:          0 :         if (stalled >= STALL_TIME)
     199                 :          0 :                 strlcat(buf, "- stalled -", win_size);
     200 [ #  # ][ #  # ]:          0 :         else if (bytes_per_second == 0 && bytes_left)
     201                 :          0 :                 strlcat(buf, "  --:-- ETA", win_size);
     202                 :            :         else {
     203         [ #  # ]:          0 :                 if (bytes_left > 0)
     204                 :          0 :                         seconds = bytes_left / bytes_per_second;
     205                 :            :                 else
     206                 :          0 :                         seconds = elapsed;
     207                 :            : 
     208                 :          0 :                 hours = seconds / 3600;
     209                 :          0 :                 seconds -= hours * 3600;
     210                 :          0 :                 minutes = seconds / 60;
     211                 :          0 :                 seconds -= minutes * 60;
     212                 :            : 
     213         [ #  # ]:          0 :                 if (hours != 0)
     214                 :          0 :                         snprintf(buf + strlen(buf), win_size - strlen(buf),
     215                 :            :                             "%d:%02d:%02d", hours, minutes, seconds);
     216                 :            :                 else
     217                 :          0 :                         snprintf(buf + strlen(buf), win_size - strlen(buf),
     218                 :            :                             "  %02d:%02d", minutes, seconds);
     219                 :            : 
     220         [ #  # ]:          0 :                 if (bytes_left > 0)
     221                 :          0 :                         strlcat(buf, " ETA", win_size);
     222                 :            :                 else
     223                 :          0 :                         strlcat(buf, "    ", win_size);
     224                 :            :         }
     225                 :            : 
     226                 :          0 :         atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1);
     227                 :          0 :         last_update = now;
     228                 :          0 : }
     229                 :            : 
     230                 :            : /*ARGSUSED*/
     231                 :            : static void
     232                 :          0 : update_progress_meter(int ignore)
     233                 :            : {
     234                 :            :         int save_errno;
     235                 :            : 
     236                 :          0 :         save_errno = errno;
     237                 :            : 
     238         [ #  # ]:          0 :         if (win_resized) {
     239                 :          0 :                 setscreensize();
     240                 :          0 :                 win_resized = 0;
     241                 :            :         }
     242         [ #  # ]:          0 :         if (can_output())
     243                 :          0 :                 refresh_progress_meter();
     244                 :            : 
     245                 :          0 :         signal(SIGALRM, update_progress_meter);
     246                 :          0 :         alarm(UPDATE_INTERVAL);
     247                 :          0 :         errno = save_errno;
     248                 :          0 : }
     249                 :            : 
     250                 :            : void
     251                 :          0 : start_progress_meter(char *f, off_t filesize, off_t *ctr)
     252                 :            : {
     253                 :          0 :         start = last_update = monotime();
     254                 :          0 :         file = f;
     255                 :          0 :         start_pos = *ctr;
     256                 :          0 :         end_pos = filesize;
     257                 :          0 :         cur_pos = 0;
     258                 :          0 :         counter = ctr;
     259                 :          0 :         stalled = 0;
     260                 :          0 :         bytes_per_second = 0;
     261                 :            : 
     262                 :          0 :         setscreensize();
     263         [ #  # ]:          0 :         if (can_output())
     264                 :          0 :                 refresh_progress_meter();
     265                 :            : 
     266                 :          0 :         signal(SIGALRM, update_progress_meter);
     267                 :          0 :         signal(SIGWINCH, sig_winch);
     268                 :          0 :         alarm(UPDATE_INTERVAL);
     269                 :          0 : }
     270                 :            : 
     271                 :            : void
     272                 :          0 : stop_progress_meter(void)
     273                 :            : {
     274                 :          0 :         alarm(0);
     275                 :            : 
     276         [ #  # ]:          0 :         if (!can_output())
     277                 :          0 :                 return;
     278                 :            : 
     279                 :            :         /* Ensure we complete the progress */
     280         [ #  # ]:          0 :         if (cur_pos != end_pos)
     281                 :          0 :                 refresh_progress_meter();
     282                 :            : 
     283                 :          0 :         atomicio(vwrite, STDOUT_FILENO, "\n", 1);
     284                 :            : }
     285                 :            : 
     286                 :            : /*ARGSUSED*/
     287                 :            : static void
     288                 :          0 : sig_winch(int sig)
     289                 :            : {
     290                 :          0 :         win_resized = 1;
     291                 :          0 : }
     292                 :            : 
     293                 :            : static void
     294                 :          0 : setscreensize(void)
     295                 :            : {
     296                 :            :         struct winsize winsize;
     297                 :            : 
     298 [ #  # ][ #  # ]:          0 :         if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 &&
     299                 :          0 :             winsize.ws_col != 0) {
     300         [ #  # ]:          0 :                 if (winsize.ws_col > MAX_WINSIZE)
     301                 :          0 :                         win_size = MAX_WINSIZE;
     302                 :            :                 else
     303                 :          0 :                         win_size = winsize.ws_col;
     304                 :            :         } else
     305                 :          0 :                 win_size = DEFAULT_WINSIZE;
     306                 :          0 :         win_size += 1;                                  /* trailing \0 */
     307                 :          0 : }

Generated by: LCOV version 1.9