LCOV - code coverage report
Current view: top level - bash-4.4.23/lib/sh - mailstat.c (source / functions) Hit Total Coverage
Test: cov-bash.info Lines: 0 56 0.0 %
Date: 2020-10-29 14:49:28 Functions: 0 1 0.0 %

          Line data    Source code
       1             : /* mailstat.c -- stat a mailbox file, handling maildir-type mail directories */
       2             : 
       3             : /* Copyright (C) 2001 Free Software Foundation, Inc.
       4             : 
       5             :    This file is part of GNU Bash, the Bourne Again SHell.
       6             : 
       7             :    Bash is free software: you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation, either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    Bash is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include <config.h>
      22             :  
      23             : #include <stdio.h>
      24             : #include <errno.h>
      25             : 
      26             : #include <bashtypes.h>
      27             : #include <posixstat.h>
      28             : #include <posixdir.h>
      29             : #include <bashansi.h>
      30             : 
      31             : #if defined (HAVE_SYS_PARAM_H)
      32             : #  include <sys/param.h>
      33             : #endif
      34             : 
      35             : #include <maxpath.h>
      36             : 
      37             : /*
      38             :  *     Stat a file. If it's a maildir, check all messages
      39             :  *     in the maildir and present the grand total as a file.
      40             :  *     The fields in the 'struct stat' are from the mail directory.
      41             :  *     The following fields are emulated:
      42             :  *
      43             :  *     st_nlink always 1, unless st_blocks is not present, in which case it's
      44             :  *              the total number of messages
      45             :  *     st_size   total number of bytes in all files
      46             :  *     st_blocks       total number of messages, if present in struct stat
      47             :  *     st_atime access time of newest file in maildir
      48             :  *     st_mtime modify time of newest file in maildir
      49             :  *     st_mode   S_IFDIR changed to S_IFREG
      50             :  *
      51             :  *     This is good enough for most mail-checking applications.
      52             :  */
      53             : 
      54             : int
      55           0 : mailstat(path, st)
      56             :      const char *path;
      57             :      struct stat *st;
      58             : {
      59           0 :   static struct stat st_new_last, st_ret_last;
      60           0 :   struct stat st_ret, st_tmp;
      61           0 :   DIR *dd;
      62           0 :   struct dirent *fn;
      63           0 :   char dir[PATH_MAX * 2], file[PATH_MAX * 2 + 1];
      64           0 :   int i, l;
      65           0 :   time_t atime, mtime;
      66             : 
      67           0 :   atime = mtime = 0;
      68             : 
      69             :   /* First see if it's a directory. */
      70           0 :   if ((i = stat(path, st)) != 0 || S_ISDIR(st->st_mode) == 0)
      71             :     return i;
      72             : 
      73           0 :   if (strlen(path) > sizeof(dir) - 5)
      74             :     {
      75             : #ifdef ENAMETOOLONG
      76           0 :       errno = ENAMETOOLONG;
      77             : #else
      78             :       errno = EINVAL;
      79             : #endif
      80           0 :       return -1;
      81             :     }
      82             : 
      83           0 :   st_ret = *st;
      84           0 :   st_ret.st_nlink = 1;
      85           0 :   st_ret.st_size  = 0;
      86             : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
      87           0 :   st_ret.st_blocks  = 0;
      88             : #else
      89             :   st_ret.st_nlink = 0;
      90             : #endif
      91           0 :   st_ret.st_mode  &= ~S_IFDIR;
      92           0 :   st_ret.st_mode  |= S_IFREG;
      93             : 
      94             :   /* See if cur/ is present */
      95           0 :   sprintf(dir, "%s/cur", path);
      96           0 :   if (stat(dir, &st_tmp) || S_ISDIR(st_tmp.st_mode) == 0)
      97             :     return 0;
      98           0 :   st_ret.st_atime = st_tmp.st_atime;
      99             : 
     100             :   /* See if tmp/ is present */
     101           0 :   sprintf(dir, "%s/tmp", path);
     102           0 :   if (stat(dir, &st_tmp) || S_ISDIR(st_tmp.st_mode) == 0)
     103             :     return 0;
     104           0 :   st_ret.st_mtime = st_tmp.st_mtime;
     105             : 
     106             :   /* And new/ */
     107           0 :   sprintf(dir, "%s/new", path);
     108           0 :   if (stat(dir, &st_tmp) || S_ISDIR(st_tmp.st_mode) == 0)
     109             :     return 0;
     110           0 :   st_ret.st_mtime = st_tmp.st_mtime;
     111             : 
     112             :   /* Optimization - if new/ didn't change, nothing else did. */
     113           0 :   if (st_tmp.st_dev == st_new_last.st_dev &&
     114           0 :       st_tmp.st_ino == st_new_last.st_ino &&
     115           0 :       st_tmp.st_atime == st_new_last.st_atime &&
     116           0 :       st_tmp.st_mtime == st_new_last.st_mtime)
     117             :     {
     118           0 :       *st = st_ret_last;
     119           0 :       return 0;
     120             :     }
     121           0 :   st_new_last = st_tmp;
     122             : 
     123             :   /* Loop over new/ and cur/ */
     124           0 :   for (i = 0; i < 2; i++)
     125             :     {
     126           0 :       sprintf(dir, "%s/%s", path, i ? "cur" : "new");
     127           0 :       sprintf(file, "%s/", dir);
     128           0 :       l = strlen(file);
     129           0 :       if ((dd = opendir(dir)) == NULL)
     130             :         return 0;
     131           0 :       while ((fn = readdir(dd)) != NULL)
     132             :         {
     133           0 :           if (fn->d_name[0] == '.' || strlen(fn->d_name) + l >= sizeof(file))
     134             :             continue;
     135           0 :           strcpy(file + l, fn->d_name);
     136           0 :           if (stat(file, &st_tmp) != 0)
     137             :             continue;
     138           0 :           st_ret.st_size += st_tmp.st_size;
     139             : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
     140           0 :           st_ret.st_blocks++;
     141             : #else
     142             :           st_ret.st_nlink++;
     143             : #endif
     144           0 :           if (st_tmp.st_atime != st_tmp.st_mtime && st_tmp.st_atime > atime)
     145           0 :             atime = st_tmp.st_atime;
     146           0 :           if (st_tmp.st_mtime > mtime)
     147           0 :             mtime = st_tmp.st_mtime;
     148             :         }
     149           0 :       closedir(dd);
     150             :     }
     151             : 
     152             : /*  if (atime) */       /* Set atime even if cur/ is empty */
     153           0 :       st_ret.st_atime = atime;
     154           0 :     if (mtime)
     155           0 :       st_ret.st_mtime = mtime;
     156             : 
     157           0 :     *st = st_ret_last = st_ret;
     158           0 :     return 0;
     159             : }

Generated by: LCOV version 1.14.0.6.4058