Ignore:
Timestamp:
Jul 8, 2013, 5:07:31 PM (8 years ago)
Author:
jordan
Message:

move platform.c's quota code into its own file. Fixes FTBFS reported in bug #5389 and is also a nice piece of encapsulation. Patch by rb07

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/platform.c

    r14080 r14110  
    1111 */
    1212
    13 #ifndef WIN32
    14  #include <sys/types.h> /* types needed by quota.h */
    15  #ifdef __FreeBSD__
    16   #include <ufs/ufs/quota.h> /* quotactl() */
    17  #elif defined (__sun)
    18   #include <sys/fs/ufs_quota.h> /* quotactl */
    19  #else
    20   #include <sys/quota.h> /* quotactl() */
    21  #endif
    22  #ifdef HAVE_GETMNTENT
    23   #ifdef __sun
    24    #include <stdio.h>
    25    #include <sys/mntent.h>
    26    #include <sys/mnttab.h>
    27    #define _PATH_MOUNTED MNTTAB
    28   #else
    29    #include <mntent.h>
    30    #include <paths.h> /* _PATH_MOUNTED */
    31   #endif
    32  #else /* BSD derived systems */
    33   #include <sys/param.h>
    34   #include <sys/ucred.h>
    35   #include <sys/mount.h>
    36  #endif
    37 #endif
     13#define _XOPEN_SOURCE 600  /* needed for recursive locks. */
     14#ifndef __USE_UNIX98
     15 #define __USE_UNIX98 /* some older Linuxes need it spelt out for them */
     16#endif
     17
     18#include <assert.h>
     19#include <stdio.h>
     20#include <stdlib.h>
     21#include <string.h>
     22#include <unistd.h> /* getuid(), close() */
     23#include <sys/stat.h>
    3824
    3925#ifdef WIN32
     
    4935  #include <FindDirectory.h>
    5036 #endif
    51  #define _XOPEN_SOURCE 600  /* needed for recursive locks. */
    52  #ifndef __USE_UNIX98
    53   #define __USE_UNIX98 /* some older Linuxes need it spelt out for them */
    54  #endif
    5537 #include <pthread.h>
    5638#endif
    5739
    58 #include <assert.h>
    59 #include <errno.h>
    60 #include <stdio.h>
    61 #include <stdlib.h>
    62 #include <string.h>
    63 
    64 #ifdef SYS_DARWIN
    65  #define HAVE_SYS_STATVFS_H
    66  #define HAVE_STATVFS
    67 #endif
    68 
    69 #include <sys/stat.h>
    70 #ifdef HAVE_SYS_STATVFS_H
    71  #include <sys/statvfs.h>
    72 #endif
    73 #ifdef WIN32
    74 #include <libgen.h>
    75 #endif
    76 #include <dirent.h>
    77 #include <fcntl.h>
    78 #include <unistd.h> /* getuid getpid close */
    79 
    80 #ifdef HAVE_XFS_XFS_H
    81  #define HAVE_XQM
    82  #include <xfs/xqm.h>
    83 #endif
    84 
    85 #include <event2/util.h> /* evutil_ascii_strcasecmp () */
     40#ifdef WIN32
     41#include <libgen.h> /* dirname() */
     42#endif
    8643
    8744#include "transmission.h"
     
    9047#include "log.h"
    9148#include "platform.h"
    92 #include "utils.h"
    9349
    9450/***
     
    612568}
    613569
    614 /***
    615 ****
    616 ***/
    617 
    618 #ifndef WIN32
    619 static const char *
    620 getdev (const char * path)
    621 {
    622 #ifdef HAVE_GETMNTENT
    623 
    624   FILE * fp;
    625 
    626 #ifdef __sun
    627   struct mnttab * mnt;
    628   fp = fopen(_PATH_MOUNTED, "r");
    629   if (fp == NULL)
    630     return NULL;
    631 
    632   while (getmntent(fp, mnt))
    633     if (!tr_strcmp0 (path, mnt->mnt_mountp))
    634       break;
    635   fclose(fp);
    636   return mnt ? mnt->mnt_fstype : NULL;
    637 #else
    638   struct mntent * mnt;
    639 
    640   fp = setmntent(_PATH_MOUNTED, "r");
    641   if (fp == NULL)
    642     return NULL;
    643 
    644   while ((mnt = getmntent(fp)) != NULL)
    645     if (!tr_strcmp0 (path, mnt->mnt_dir))
    646       break;
    647 
    648   endmntent(fp);
    649   return mnt ? mnt->mnt_fsname : NULL;
    650 #endif
    651 #else /* BSD derived systems */
    652 
    653   int i;
    654   int n;
    655   struct statfs * mnt;
    656 
    657   n = getmntinfo(&mnt, MNT_WAIT);
    658   if (!n)
    659     return NULL;
    660 
    661   for (i=0; i<n; i++)
    662     if (!tr_strcmp0 (path, mnt[i].f_mntonname))
    663       break;
    664 
    665   return (i < n) ? mnt[i].f_mntfromname : NULL;
    666 
    667 #endif
    668 }
    669 
    670 static const char *
    671 getfstype (const char * device)
    672 {
    673 
    674 #ifdef HAVE_GETMNTENT
    675 
    676   FILE * fp;
    677 #ifdef __sun
    678   struct mnttab *mnt;
    679   fp = fopen(_PATH_MOUNTED, "r");
    680   if (fp == NULL)
    681     return NULL;
    682   while (getmntent(fp, mnt))
    683     if (!tr_strcmp0 (device, mnt->mnt_mountp))
    684       break;
    685   fclose(fp);
    686   return mnt ? mnt->mnt_fstype : NULL;
    687 #else
    688   struct mntent *mnt;
    689 
    690   fp = setmntent (_PATH_MOUNTED, "r");
    691   if (fp == NULL)
    692     return NULL;
    693 
    694   while ((mnt = getmntent (fp)) != NULL)
    695     if (!tr_strcmp0 (device, mnt->mnt_fsname))
    696       break;
    697 
    698   endmntent(fp);
    699   return mnt ? mnt->mnt_type : NULL;
    700 #endif
    701 #else /* BSD derived systems */
    702 
    703   int i;
    704   int n;
    705   struct statfs *mnt;
    706 
    707   n = getmntinfo(&mnt, MNT_WAIT);
    708   if (!n)
    709     return NULL;
    710 
    711   for (i=0; i<n; i++)
    712     if (!tr_strcmp0 (device, mnt[i].f_mntfromname))
    713       break;
    714 
    715   return (i < n) ? mnt[i].f_fstypename : NULL;
    716 
    717 #endif
    718 }
    719 
    720 static const char *
    721 getblkdev (const char * path)
    722 {
    723   char * c;
    724   char * dir;
    725   const char * device;
    726 
    727   dir = tr_strdup(path);
    728 
    729   for (;;)
    730     {
    731       device = getdev (dir);
    732       if (device != NULL)
    733         break;
    734 
    735       c = strrchr (dir, '/');
    736       if (c != NULL)
    737         *c = '\0';
    738       else
    739          break;
    740     }
    741 
    742   tr_free (dir);
    743   return device;
    744 }
    745 
    746 static int64_t
    747 getquota (const char * device)
    748 {
    749   struct dqblk dq;
    750   int64_t limit;
    751   int64_t freespace;
    752   int64_t spaceused;
    753 
    754 #if defined(__FreeBSD__) || defined(SYS_DARWIN)
    755   if (quotactl(device, QCMD(Q_GETQUOTA, USRQUOTA), getuid(), (caddr_t) &dq) == 0)
    756     {
    757 #elif defined(__sun)
    758   struct quotctl  op;
    759   int fd = open(device, O_RDONLY);
    760   if (fd < 0)
    761     return -1;
    762   op.op = Q_GETQUOTA;
    763   op.uid = getuid();
    764   op.addr = (caddr_t) &dq;
    765   if (ioctl(fd, Q_QUOTACTL, &op) == 0)
    766     {
    767       close(fd);
    768 #else
    769   if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device, getuid(), (caddr_t) &dq) == 0)
    770     {
    771 #endif
    772       if (dq.dqb_bsoftlimit > 0)
    773         {
    774           /* Use soft limit first */
    775           limit = dq.dqb_bsoftlimit;
    776         }
    777       else if (dq.dqb_bhardlimit > 0)
    778         {
    779           limit = dq.dqb_bhardlimit;
    780         }
    781       else
    782         {
    783           /* No quota enabled for this user */
    784           return -1;
    785         }
    786 #if defined(__FreeBSD__)
    787       spaceused = (int64_t) dq.dqb_curblocks >> 1;
    788 #elif defined(SYS_DARWIN)
    789       spaceused = (int64_t) dq.dqb_curbytes;
    790 #elif defined(__UCLIBC__)
    791       spaceused = (int64_t) btodb(dq.dqb_curblocks);
    792 #elif defined(__sun)
    793       spaceused = (int64_t) dq.dqb_curblocks >> 1;
    794 #else
    795       spaceused = btodb(dq.dqb_curspace);
    796 #endif
    797       freespace = limit - spaceused;
    798 #ifdef SYS_DARWIN
    799       return (freespace < 0) ? 0 : freespace;
    800 #else
    801       return (freespace < 0) ? 0 : freespace * 1024;
    802 #endif
    803     }
    804 #if defined(__sun)
    805   close(fd);
    806 #endif
    807   /* something went wrong */
    808   return -1;
    809 }
    810 
    811 #ifdef HAVE_XQM
    812 static int64_t
    813 getxfsquota (char * device)
    814 {
    815   int64_t limit;
    816   int64_t freespace;
    817   struct fs_disk_quota dq;
    818 
    819   if (quotactl(QCMD(Q_XGETQUOTA, USRQUOTA), device, getuid(), (caddr_t) &dq) == 0)
    820     {
    821       if (dq.d_blk_softlimit > 0)
    822         {
    823           /* Use soft limit first */
    824           limit = dq.d_blk_softlimit >> 1;
    825         }
    826       else if (dq.d_blk_hardlimit > 0)
    827         {
    828           limit = dq.d_blk_hardlimit >> 1;
    829         }
    830       else
    831         {
    832           /* No quota enabled for this user */
    833           return -1;
    834         }
    835 
    836       freespace = limit - (dq.d_bcount >> 1);
    837       return (freespace < 0) ? 0 : freespace * 1024;
    838     }
    839 
    840   /* something went wrong */
    841   return -1;
    842 }
    843 #endif /* HAVE_XQM */
    844 #endif /* WIN32 */
    845 
    846 static int64_t
    847 tr_getQuotaFreeSpace (const struct tr_device_info * info)
    848 {
    849   int64_t ret = -1;
    850 
    851 #ifndef WIN32
    852 
    853   if (info->fstype && !evutil_ascii_strcasecmp(info->fstype, "xfs"))
    854     {
    855 #ifdef HAVE_XQM
    856       ret = getxfsquota (info->device);
    857 #endif
    858     }
    859   else
    860     {
    861       ret = getquota (info->device);
    862     }
    863 #endif /* WIN32 */
    864 
    865   return ret;
    866 }
    867 
    868 static int64_t
    869 tr_getDiskFreeSpace (const char * path)
    870 {
    871 #ifdef WIN32
    872 
    873   uint64_t freeBytesAvailable = 0;
    874   return GetDiskFreeSpaceEx (path, &freeBytesAvailable, NULL, NULL)
    875     ? (int64_t)freeBytesAvailable
    876     : -1;
    877 
    878 #elif defined(HAVE_STATVFS)
    879 
    880   struct statvfs buf;
    881   return statvfs(path, &buf) ? -1 : (int64_t)buf.f_bavail * (int64_t)buf.f_frsize;
    882 
    883 #else
    884 
    885   #warning FIXME: not implemented
    886   return -1;
    887 
    888 #endif
    889 }
    890 
    891 struct tr_device_info *
    892 tr_device_info_create (const char * path)
    893 {
    894   struct tr_device_info * info;
    895 
    896   info = tr_new0 (struct tr_device_info, 1);
    897   info->path = tr_strdup (path);
    898 #ifndef WIN32
    899   info->device = tr_strdup (getblkdev (path));
    900   info->fstype = tr_strdup (getfstype (path));
    901 #endif
    902 
    903   return info;
    904 }
    905 
    906 void
    907 tr_device_info_free (struct tr_device_info * info)
    908 {
    909   if (info != NULL)
    910     {
    911       tr_free (info->fstype);
    912       tr_free (info->device);
    913       tr_free (info->path);
    914       tr_free (info);
    915     }
    916 }
    917 
    918 int64_t
    919 tr_device_info_get_free_space (const struct tr_device_info * info)
    920 {
    921   int64_t free_space;
    922 
    923   if ((info == NULL) || (info->path == NULL))
    924     {
    925       errno = EINVAL;
    926       free_space = -1;
    927     }
    928   else
    929     {
    930       free_space = tr_getQuotaFreeSpace (info);
    931 
    932       if (free_space < 0)
    933         free_space = tr_getDiskFreeSpace (info->path);
    934     }
    935 
    936   return free_space;
    937 }
    938 
    939 /***
    940 ****
    941 ***/
    942570
    943571#ifdef WIN32
Note: See TracChangeset for help on using the changeset viewer.