smbd/dfree.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    functions to calculate the free disk space
00004    Copyright (C) Andrew Tridgell 1998
00005    
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 #include "includes.h"
00022 
00023 /****************************************************************************
00024  Normalise for DOS usage.
00025 ****************************************************************************/
00026 
00027 static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
00028 {
00029         /* check if the disk is beyond the max disk size */
00030         SMB_BIG_UINT maxdisksize = lp_maxdisksize();
00031         if (maxdisksize) {
00032                 /* convert to blocks - and don't overflow */
00033                 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
00034                 if (*dsize > maxdisksize) *dsize = maxdisksize;
00035                 if (*dfree > maxdisksize) *dfree = maxdisksize-1; 
00036                 /* the -1 should stop applications getting div by 0
00037                    errors */
00038         }  
00039 
00040         if(small_query) {       
00041                 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) {
00042                         *dfree /= 2;
00043                         *dsize /= 2;
00044                         *bsize *= 2;
00045                         /*
00046                          * Force max to fit in 16 bit fields.
00047                          */
00048                         if (*bsize > (WORDMAX*512)) {
00049                                 *bsize = (WORDMAX*512);
00050                                 if (*dsize > WORDMAX)
00051                                         *dsize = WORDMAX;
00052                                 if (*dfree >  WORDMAX)
00053                                         *dfree = WORDMAX;
00054                                 break;
00055                         }
00056                 }
00057         }
00058 }
00059 
00060 
00061 
00062 /****************************************************************************
00063  Return number of 1K blocks available on a path and total number.
00064 ****************************************************************************/
00065 
00066 SMB_BIG_UINT sys_disk_free(connection_struct *conn, const char *path, BOOL small_query, 
00067                               SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
00068 {
00069         SMB_BIG_UINT dfree_retval;
00070         SMB_BIG_UINT dfree_q = 0;
00071         SMB_BIG_UINT bsize_q = 0;
00072         SMB_BIG_UINT dsize_q = 0;
00073         const char *dfree_command;
00074 
00075         (*dfree) = (*dsize) = 0;
00076         (*bsize) = 512;
00077 
00078         /*
00079          * If external disk calculation specified, use it.
00080          */
00081 
00082         dfree_command = lp_dfree_command(SNUM(conn));
00083         if (dfree_command && *dfree_command) {
00084                 const char *p;
00085                 char **lines;
00086                 pstring syscmd;
00087 
00088                 slprintf(syscmd, sizeof(syscmd)-1, "%s %s", dfree_command, path);
00089                 DEBUG (3, ("disk_free: Running command %s\n", syscmd));
00090 
00091                 lines = file_lines_pload(syscmd, NULL);
00092                 if (lines) {
00093                         char *line = lines[0];
00094 
00095                         DEBUG (3, ("Read input from dfree, \"%s\"\n", line));
00096 
00097                         *dsize = STR_TO_SMB_BIG_UINT(line, &p);
00098                         while (p && *p && isspace(*p))
00099                                 p++;
00100                         if (p && *p)
00101                                 *dfree = STR_TO_SMB_BIG_UINT(p, &p);
00102                         while (p && *p && isspace(*p))
00103                                 p++;
00104                         if (p && *p)
00105                                 *bsize = STR_TO_SMB_BIG_UINT(p, NULL);
00106                         else
00107                                 *bsize = 1024;
00108                         file_lines_free(lines);
00109                         DEBUG (3, ("Parsed output of dfree, dsize=%u, dfree=%u, bsize=%u\n",
00110                                 (unsigned int)*dsize, (unsigned int)*dfree, (unsigned int)*bsize));
00111 
00112                         if (!*dsize)
00113                                 *dsize = 2048;
00114                         if (!*dfree)
00115                                 *dfree = 1024;
00116                 } else {
00117                         DEBUG (0, ("disk_free: sys_popen() failed for command %s. Error was : %s\n",
00118                                 syscmd, strerror(errno) ));
00119                         if (sys_fsusage(path, dfree, dsize) != 0) {
00120                                 DEBUG (0, ("disk_free: sys_fsusage() failed. Error was : %s\n",
00121                                         strerror(errno) ));
00122                                 return (SMB_BIG_UINT)-1;
00123                         }
00124                 }
00125         } else {
00126                 if (sys_fsusage(path, dfree, dsize) != 0) {
00127                         DEBUG (0, ("disk_free: sys_fsusage() failed. Error was : %s\n",
00128                                 strerror(errno) ));
00129                         return (SMB_BIG_UINT)-1;
00130                 }
00131         }
00132 
00133         if (disk_quotas(path, &bsize_q, &dfree_q, &dsize_q)) {
00134                 (*bsize) = bsize_q;
00135                 (*dfree) = MIN(*dfree,dfree_q);
00136                 (*dsize) = MIN(*dsize,dsize_q);
00137         }
00138 
00139         /* FIXME : Any reason for this assumption ? */
00140         if (*bsize < 256) {
00141                 DEBUG(5,("disk_free:Warning: bsize == %d < 256 . Changing to assumed correct bsize = 512\n",(int)*bsize));
00142                 *bsize = 512;
00143         }
00144 
00145         if ((*dsize)<1) {
00146                 static int done;
00147                 if (!done) {
00148                         DEBUG(0,("WARNING: dfree is broken on this system\n"));
00149                         done=1;
00150                 }
00151                 *dsize = 20*1024*1024/(*bsize);
00152                 *dfree = MAX(1,*dfree);
00153         }
00154 
00155         disk_norm(small_query,bsize,dfree,dsize);
00156 
00157         if ((*bsize) < 1024) {
00158                 dfree_retval = (*dfree)/(1024/(*bsize));
00159         } else {
00160                 dfree_retval = ((*bsize)/1024)*(*dfree);
00161         }
00162 
00163         return(dfree_retval);
00164 }
00165 
00166 /****************************************************************************
00167  Potentially returned cached dfree info.
00168 ****************************************************************************/
00169 
00170 SMB_BIG_UINT get_dfree_info(connection_struct *conn,
00171                         const char *path,
00172                         BOOL small_query,
00173                         SMB_BIG_UINT *bsize,
00174                         SMB_BIG_UINT *dfree,
00175                         SMB_BIG_UINT *dsize)
00176 {
00177         int dfree_cache_time = lp_dfree_cache_time(SNUM(conn));
00178         struct dfree_cached_info *dfc = conn->dfree_info;
00179         SMB_BIG_UINT dfree_ret;
00180 
00181         if (!dfree_cache_time) {
00182                 return SMB_VFS_DISK_FREE(conn,path,small_query,bsize,dfree,dsize);
00183         }
00184 
00185         if (dfc && (conn->lastused - dfc->last_dfree_time < dfree_cache_time)) {
00186                 /* Return cached info. */
00187                 *bsize = dfc->bsize;
00188                 *dfree = dfc->dfree;
00189                 *dsize = dfc->dsize;
00190                 return dfc->dfree_ret;
00191         }
00192 
00193         dfree_ret = SMB_VFS_DISK_FREE(conn,path,small_query,bsize,dfree,dsize);
00194 
00195         if (dfree_ret == (SMB_BIG_UINT)-1) {
00196                 /* Don't cache bad data. */
00197                 return dfree_ret;
00198         }
00199 
00200         /* No cached info or time to refresh. */
00201         if (!dfc) {
00202                 dfc = TALLOC_P(conn->mem_ctx, struct dfree_cached_info);
00203                 if (!dfc) {
00204                         return dfree_ret;
00205                 }
00206                 conn->dfree_info = dfc;
00207         }
00208 
00209         dfc->bsize = *bsize;
00210         dfc->dfree = *dfree;
00211         dfc->dsize = *dsize;
00212         dfc->dfree_ret = dfree_ret;
00213         dfc->last_dfree_time = conn->lastused;
00214 
00215         return dfree_ret;
00216 }

Sambaに対してSat Aug 29 21:23:23 2009に生成されました。  doxygen 1.4.7