⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 storage.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 2 页
字号:
/*     This file is part of GNUnet.     (C) 2001, 2002, 2005, 2006 Christian Grothoff (and other contributing authors)     GNUnet is free software; you can redistribute it and/or modify     it under the terms of the GNU General Public License as published     by the Free Software Foundation; either version 2, or (at your     option) any later version.     GNUnet is distributed in the hope that it will be useful, but     WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     General Public License for more details.     You should have received a copy of the GNU General Public License     along with GNUnet; see the file COPYING.  If not, write to the     Free Software Foundation, Inc., 59 Temple Place - Suite 330,     Boston, MA 02111-1307, USA.*//** * @file util/disk/storage.c * @brief disk IO convenience methods * @author Christian Grothoff */#include "platform.h"#include "gnunet_util_string.h"#include "gnunet_util_disk.h"#if LINUX || CYGWIN#include <sys/vfs.h>#else#ifdef SOMEBSD#include <sys/param.h>#include <sys/mount.h>#else#ifdef OSX#include <sys/param.h>#include <sys/mount.h>#else#ifdef SOLARIS#include <sys/types.h>#include <sys/statvfs.h>#else#ifdef MINGW#define  	_IFMT		0170000 /* type of file */#define  	_IFLNK		0120000 /* symbolic link */#define  S_ISLNK(m)	(((m)&_IFMT) == _IFLNK)#else#error PORT-ME: need to port statfs (how much space is left on the drive?)#endif#endif#endif#endif#endif#ifndef SOMEBSD#ifndef WINDOWS#ifndef OSX#include <wordexp.h>#endif#endif#endiftypedef struct{  struct GNUNET_GE_Context *ectx;  unsigned long long total;  int include_sym_links;} GetFileSizeData;static intgetSizeRec (const char *filename, const char *dirname, void *ptr){  GetFileSizeData *gfsd = ptr;#ifdef HAVE_STAT64  struct stat64 buf;#else  struct stat buf;#endif  char *fn;  GNUNET_GE_ASSERT (gfsd->ectx, filename != NULL);  if ((dirname != NULL) && (strlen (dirname) > 0))    {      fn = GNUNET_malloc (strlen (filename) + strlen (dirname) + 3);      if (strlen (dirname) > 0)        {          strcpy (fn, dirname);          if (dirname[strlen (dirname) - 1] != DIR_SEPARATOR)            strcat (fn, DIR_SEPARATOR_STR);     /* add tailing / if needed */        }      /* Windows paths don't start with / */#ifndef MINGW      else        strcpy (fn, DIR_SEPARATOR_STR);#endif      if (filename[0] == DIR_SEPARATOR)        /* if filename starts with a "/", don't copy it */        strcat (fn, &filename[1]);      else        strcat (fn, filename);    }  else    fn = GNUNET_strdup (filename);#ifdef HAVE_STAT64  if (0 != STAT64 (fn, &buf))    {      GNUNET_GE_LOG_STRERROR_FILE (gfsd->ectx,                                   GNUNET_GE_WARNING | GNUNET_GE_USER |                                   GNUNET_GE_REQUEST, "stat64", fn);      GNUNET_free (fn);      return GNUNET_SYSERR;    }#else  if (0 != STAT (fn, &buf))    {      GNUNET_GE_LOG_STRERROR_FILE (gfsd->ectx,                                   GNUNET_GE_WARNING | GNUNET_GE_USER |                                   GNUNET_GE_REQUEST, "stat", fn);      GNUNET_free (fn);      return GNUNET_SYSERR;    }#endif  if ((!S_ISLNK (buf.st_mode)) || (gfsd->include_sym_links == GNUNET_YES))    gfsd->total += buf.st_size;  if ((S_ISDIR (buf.st_mode)) &&      (0 == ACCESS (fn, X_OK)) &&      ((!S_ISLNK (buf.st_mode)) || (gfsd->include_sym_links == GNUNET_YES)))    {      if (GNUNET_SYSERR ==          GNUNET_disk_directory_scan (gfsd->ectx, fn, &getSizeRec, gfsd))        {          GNUNET_free (fn);          return GNUNET_SYSERR;        }    }  GNUNET_free (fn);  return GNUNET_OK;}/** * Get the size of the file (or directory) * of the given file (in bytes). * * @return GNUNET_SYSERR on error, GNUNET_OK on success */intGNUNET_disk_file_size (struct GNUNET_GE_Context *ectx,                       const char *filename,                       unsigned long long *size, int includeSymLinks){  GetFileSizeData gfsd;  int ret;  GNUNET_GE_ASSERT (ectx, size != NULL);  gfsd.ectx = ectx;  gfsd.total = 0;  gfsd.include_sym_links = includeSymLinks;  ret = getSizeRec (filename, "", &gfsd);  *size = gfsd.total;  return ret;}/** * Get the number of blocks that are left on the partition that * contains the given file (for normal users). * * @param part a file on the partition to check * @return -1 on errors, otherwise the number of free blocks */longGNUNET_disk_get_blocks_available (struct GNUNET_GE_Context *ectx,                                  const char *part){#ifdef SOLARIS  struct statvfs buf;  if (0 != statvfs (part, &buf))    {      GNUNET_GE_LOG_STRERROR_FILE (ectx,                                   GNUNET_GE_WARNING | GNUNET_GE_USER |                                   GNUNET_GE_ADMIN | GNUNET_GE_BULK, "statfs",                                   part);      return -1;    }  return buf.f_bavail;#elif MINGW  DWORD dwDummy;  DWORD dwBlocks;  char szDrive[4];  memcpy (szDrive, part, 3);  szDrive[3] = 0;  if (!GetDiskFreeSpace (szDrive, &dwDummy, &dwDummy, &dwBlocks, &dwDummy))    {      GNUNET_GE_LOG (ectx,                     GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_ADMIN |                     GNUNET_GE_BULK, _("`%s' failed for drive `%s': %u\n"),                     "GetDiskFreeSpace", szDrive, GetLastError ());      return -1;    }  return dwBlocks;#else  struct statfs s;  if (0 != statfs (part, &s))    {      GNUNET_GE_LOG_STRERROR_FILE (ectx,                                   GNUNET_GE_WARNING | GNUNET_GE_USER |                                   GNUNET_GE_ADMIN | GNUNET_GE_BULK, "statfs",                                   part);      return -1;    }  return s.f_bavail;#endif}/** * Test if fil is a directory. * * @return GNUNET_YES if yes, GNUNET_NO if not, GNUNET_SYSERR if it *   does not exist */intGNUNET_disk_directory_test (struct GNUNET_GE_Context *ectx, const char *fil){  struct stat filestat;  int ret;  ret = STAT (fil, &filestat);  if (ret != 0)    {      if (errno != ENOENT)        {          GNUNET_GE_LOG_STRERROR_FILE (ectx,                                       GNUNET_GE_WARNING | GNUNET_GE_USER |                                       GNUNET_GE_ADMIN | GNUNET_GE_REQUEST,                                       "stat", fil);          return GNUNET_SYSERR;        }      return GNUNET_NO;    }  if (!S_ISDIR (filestat.st_mode))    return GNUNET_NO;  if (ACCESS (fil, R_OK | X_OK) < 0)    {      GNUNET_GE_LOG_STRERROR_FILE (ectx,                                   GNUNET_GE_WARNING | GNUNET_GE_USER |                                   GNUNET_GE_ADMIN | GNUNET_GE_REQUEST,                                   "access", fil);      return GNUNET_SYSERR;    }  return GNUNET_YES;}/** * Check that fil corresponds to a filename * (of a file that exists and that is not a directory). * @returns GNUNET_YES if yes, GNUNET_NO if not a file, GNUNET_SYSERR if something * else (will print an error message in that case, too). */intGNUNET_disk_file_test (struct GNUNET_GE_Context *ectx, const char *fil){  struct stat filestat;  int ret;  char *rdir;  rdir = GNUNET_expand_file_name (ectx, fil);  if (rdir == NULL)    return GNUNET_SYSERR;  ret = STAT (rdir, &filestat);  if (ret != 0)    {      if (errno != ENOENT)        {          GNUNET_GE_LOG_STRERROR_FILE (ectx,                                       GNUNET_GE_WARNING | GNUNET_GE_USER |                                       GNUNET_GE_ADMIN | GNUNET_GE_REQUEST,                                       "stat", rdir);          GNUNET_free (rdir);          return GNUNET_SYSERR;        }      GNUNET_free (rdir);      return GNUNET_NO;    }  if (!S_ISREG (filestat.st_mode))    {      GNUNET_free (rdir);      return GNUNET_NO;    }  if (ACCESS (rdir, R_OK) < 0)    {      GNUNET_GE_LOG_STRERROR_FILE (ectx,                                   GNUNET_GE_WARNING | GNUNET_GE_USER |                                   GNUNET_GE_ADMIN | GNUNET_GE_REQUEST,                                   "access", rdir);      GNUNET_free (rdir);      return GNUNET_SYSERR;    }  GNUNET_free (rdir);  return GNUNET_YES;}/** * Implementation of "mkdir -p" * @param dir the directory to create * @returns GNUNET_OK on success, GNUNET_SYSERR on failure */intGNUNET_disk_directory_create (struct GNUNET_GE_Context *ectx, const char *dir){  char *rdir;  int len;  int pos;  int ret = GNUNET_OK;  rdir = GNUNET_expand_file_name (ectx, dir);  if (rdir == NULL)    return GNUNET_SYSERR;  len = strlen (rdir);#ifndef MINGW  pos = 1;                      /* skip heading '/' */#else  /* Local or Network path? */  if (strncmp (rdir, "\\\\", 2) == 0)    {      pos = 2;      while (rdir[pos])        {          if (rdir[pos] == '\\')            {              pos++;              break;            }          pos++;        }    }  else    {      pos = 3;                  /* strlen("C:\\") */    }#endif  while (pos <= len)    {      if ((rdir[pos] == DIR_SEPARATOR) || (pos == len))        {          rdir[pos] = '\0';          ret = GNUNET_disk_directory_test (ectx, rdir);          if (ret == GNUNET_SYSERR)            {              GNUNET_free (rdir);              return GNUNET_SYSERR;            }          if (ret == GNUNET_NO)            {#ifndef MINGW              ret = mkdir (rdir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);  /* 755 */#else              ret = mkdir (rdir);#endif              if ((ret != 0) && (errno != EEXIST))                {                  GNUNET_GE_LOG_STRERROR_FILE (ectx,                                               GNUNET_GE_ERROR |                                               GNUNET_GE_USER |                                               GNUNET_GE_BULK, "mkdir", rdir);                  GNUNET_free (rdir);                  return GNUNET_SYSERR;                }            }          rdir[pos] = DIR_SEPARATOR;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -