From 8fb4b6843e2d8b181962cc92681bf54005f5f470 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1=D1?=
 =?UTF-8?q?=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= <lrn1986@gmail.com>
Date: Mon, 19 Mar 2012 10:30:43 +0400
Subject: [PATCH 2/4] Calculate file size for single files when needed

---
 src/fs/fs_download.c                  |    4 ++--
 src/fs/fs_unindex.c                   |    2 +-
 src/fs/gnunet-directory.c             |    2 +-
 src/fs/test_fs_download.c             |    2 +-
 src/fs/test_fs_download_indexed.c     |    2 +-
 src/fs/test_fs_download_persistence.c |    2 +-
 src/hello/gnunet-hello.c              |    2 +-
 src/include/gnunet_disk_lib.h         |   10 ++++++----
 src/testing/gnunet-testing.c          |    2 +-
 src/testing/testing_group.c           |    2 +-
 src/transport/transport-testing.c     |    2 +-
 src/util/crypto_hash.c                |    2 +-
 src/util/crypto_rsa.c                 |    2 +-
 src/util/disk.c                       |   17 +++++++++++++++--
 src/util/pseudonym.c                  |    4 ++--
 src/util/test_disk.c                  |    2 +-
 16 files changed, 37 insertions(+), 22 deletions(-)

diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c
index 0596d85..490beef 100644
--- a/src/fs/fs_download.c
+++ b/src/fs/fs_download.c
@@ -2068,7 +2068,7 @@ GNUNET_FS_download_start (struct GNUNET_FS_Handle *h,
   {
     dc->filename = GNUNET_strdup (filename);
     if (GNUNET_YES == GNUNET_DISK_file_test (filename))
-      GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (filename, &dc->old_file_size, GNUNET_YES));
+      GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (filename, &dc->old_file_size, GNUNET_YES, GNUNET_YES));
   }
   if (GNUNET_FS_uri_test_loc (dc->uri))
     GNUNET_assert (GNUNET_OK ==
@@ -2178,7 +2178,7 @@ GNUNET_FS_download_start_from_search (struct GNUNET_FS_Handle *h,
   {
     dc->filename = GNUNET_strdup (filename);
     if (GNUNET_YES == GNUNET_DISK_file_test (filename))
-      GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (filename, &dc->old_file_size, GNUNET_YES));
+      GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (filename, &dc->old_file_size, GNUNET_YES, GNUNET_YES));
   }
   if (GNUNET_FS_uri_test_loc (dc->uri))
     GNUNET_assert (GNUNET_OK ==
diff --git a/src/fs/fs_unindex.c b/src/fs/fs_unindex.c
index 3c2ef8f..bf619b7 100644
--- a/src/fs/fs_unindex.c
+++ b/src/fs/fs_unindex.c
@@ -755,7 +755,7 @@ GNUNET_FS_unindex_start (struct GNUNET_FS_Handle *h, const char *filename,
   struct GNUNET_FS_ProgressInfo pi;
   uint64_t size;
 
-  if (GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES))
+  if (GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES, GNUNET_YES))
     return NULL;
   ret = GNUNET_malloc (sizeof (struct GNUNET_FS_UnindexContext));
   ret->h = h;
diff --git a/src/fs/gnunet-directory.c b/src/fs/gnunet-directory.c
index 0721ea9..c722f57 100644
--- a/src/fs/gnunet-directory.c
+++ b/src/fs/gnunet-directory.c
@@ -136,7 +136,7 @@ run (void *cls, char *const *args, const char *cfgfile,
   i = 0;
   while (NULL != (filename = args[i++]))
   {
-    if ((GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES)) ||
+    if ((GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES, GNUNET_YES)) ||
         (NULL ==
          (h =
           GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
diff --git a/src/fs/test_fs_download.c b/src/fs/test_fs_download.c
index 570eab9..198a815 100644
--- a/src/fs/test_fs_download.c
+++ b/src/fs/test_fs_download.c
@@ -118,7 +118,7 @@ abort_download_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     GNUNET_FS_download_stop (download, GNUNET_YES);
     download = NULL;
   }
-  GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES));
+  GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES, GNUNET_NO));
   GNUNET_assert (size == FILESIZE);
   GNUNET_DISK_directory_remove (fn);
   GNUNET_free (fn);
diff --git a/src/fs/test_fs_download_indexed.c b/src/fs/test_fs_download_indexed.c
index e8504f1..c00b9e7 100644
--- a/src/fs/test_fs_download_indexed.c
+++ b/src/fs/test_fs_download_indexed.c
@@ -119,7 +119,7 @@ abort_download_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     GNUNET_FS_download_stop (download, GNUNET_YES);
     download = NULL;
   }
-  GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES));
+  GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES, GNUNET_NO));
   GNUNET_assert (size == FILESIZE);
   GNUNET_DISK_directory_remove (fn);
   GNUNET_free (fn);
diff --git a/src/fs/test_fs_download_persistence.c b/src/fs/test_fs_download_persistence.c
index bcb1c54..3a6d955 100644
--- a/src/fs/test_fs_download_persistence.c
+++ b/src/fs/test_fs_download_persistence.c
@@ -113,7 +113,7 @@ abort_download_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     GNUNET_FS_download_stop (download, GNUNET_YES);
     download = NULL;
   }
-  GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES));
+  GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES, GNUNET_NO));
   GNUNET_assert (size == FILESIZE);
   GNUNET_DISK_directory_remove (fn);
   GNUNET_free (fn);
diff --git a/src/hello/gnunet-hello.c b/src/hello/gnunet-hello.c
index be7719e..9cf32f9 100644
--- a/src/hello/gnunet-hello.c
+++ b/src/hello/gnunet-hello.c
@@ -122,7 +122,7 @@ main (int argc, char *argv[])
 	     _("Call with name of HELLO file to modify.\n"));
     return 1;
   }
-  if (GNUNET_OK != GNUNET_DISK_file_size (argv[1], &fsize, GNUNET_YES))
+  if (GNUNET_OK != GNUNET_DISK_file_size (argv[1], &fsize, GNUNET_YES, GNUNET_YES))
   {
     FPRINTF (stderr,
 	     _("Error accessing file `%s': %s\n"),
diff --git a/src/include/gnunet_disk_lib.h b/src/include/gnunet_disk_lib.h
index 18f5535..d6ec0fe 100644
--- a/src/include/gnunet_disk_lib.h
+++ b/src/include/gnunet_disk_lib.h
@@ -302,8 +302,8 @@ GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle *h, OFF_T offset,
 
 
 /**
- * Get the size of the file (or directory)
- * of the given file (in bytes).
+ * Get the size of the file (or directory) of the given file (in
+ * bytes).
  *
  * @param filename name of the file or directory
  * @param size set to the size of the file (or,
@@ -311,11 +311,13 @@ GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle *h, OFF_T offset,
  *             of all sizes of files in the directory)
  * @param includeSymLinks should symbolic links be
  *        included?
- * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ * @param singleFileMode GNUNET_YES to only get size of one file
+ *        and return GNUNET_SYSERR for directories.
+ * @return GNUNET_SYSERR on error, GNUNET_OK on success
  */
 int
 GNUNET_DISK_file_size (const char *filename, uint64_t * size,
-                       int includeSymLinks);
+                       int includeSymLinks, int singleFileMode);
 
 
 /**
diff --git a/src/testing/gnunet-testing.c b/src/testing/gnunet-testing.c
index 0caa28e..3f6eb8a 100644
--- a/src/testing/gnunet-testing.c
+++ b/src/testing/gnunet-testing.c
@@ -170,7 +170,7 @@ create_hostkeys (const unsigned int no)
       return 1;
     }
 
-    if (GNUNET_YES != GNUNET_DISK_file_size (hostkey_src_file, &fs, GNUNET_YES))
+    if (GNUNET_YES != GNUNET_DISK_file_size (hostkey_src_file, &fs, GNUNET_YES, GNUNET_YES))
       fs = 0;
 
     if (0 != (fs % HOSTKEYFILESIZE))
diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c
index e8db98a..983a5ab 100644
--- a/src/testing/testing_group.c
+++ b/src/testing/testing_group.c
@@ -6078,7 +6078,7 @@ GNUNET_TESTING_daemons_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
         return NULL;
       }
 
-      if (GNUNET_YES != GNUNET_DISK_file_size (hostkeys_file, &fs, GNUNET_YES))
+      if (GNUNET_YES != GNUNET_DISK_file_size (hostkeys_file, &fs, GNUNET_YES, GNUNET_YES))
         fs = 0;
 #if DEBUG_TESTING
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
diff --git a/src/transport/transport-testing.c b/src/transport/transport-testing.c
index 752106b..6a27d99 100644
--- a/src/transport/transport-testing.c
+++ b/src/transport/transport-testing.c
@@ -661,7 +661,7 @@ GNUNET_TRANSPORT_TESTING_init ()
       return NULL;
     }
 
-    if (GNUNET_YES != GNUNET_DISK_file_size (hostkeys_file, &fs, GNUNET_YES))
+    if (GNUNET_YES != GNUNET_DISK_file_size (hostkeys_file, &fs, GNUNET_YES, GNUNET_YES))
       fs = 0;
 
     if (0 != (fs % HOSTKEYFILESIZE))
diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c
index f896390..a7f9c4c 100644
--- a/src/util/crypto_hash.c
+++ b/src/util/crypto_hash.c
@@ -204,7 +204,7 @@ GNUNET_CRYPTO_hash_file (enum GNUNET_SCHEDULER_Priority priority,
     return NULL;
   }
   fhc->bsize = blocksize;
-  if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fhc->fsize, GNUNET_NO))
+  if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fhc->fsize, GNUNET_NO, GNUNET_YES))
   {
     GNUNET_free (fhc->filename);
     GNUNET_free (fhc);
diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c
index ee7e5e9..54d61b1 100644
--- a/src/util/crypto_rsa.c
+++ b/src/util/crypto_rsa.c
@@ -726,7 +726,7 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename)
 
       return NULL;
     }
-    if (GNUNET_YES != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES))
+    if (GNUNET_YES != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
       fs = 0;
     if (fs < sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded))
     {
diff --git a/src/util/disk.c b/src/util/disk.c
index b6b458f..ae3ac4c 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -112,6 +112,11 @@ struct GetFileSizeData
    * GNUNET_YES if symbolic links should be included.
    */
   int include_sym_links;
+
+  /**
+   * GNUNET_YES if mode is file-only (return total == -1 for directories).
+   */
+  int single_file_mode;
 };
 
 
@@ -176,6 +181,11 @@ getSizeRec (void *cls, const char *fn)
     return GNUNET_SYSERR;
   }
 #endif
+  if ((S_ISDIR (buf.st_mode)) && (gfsd->single_file_mode == GNUNET_YES))
+  {
+    errno = EISDIR;
+    return GNUNET_SYSERR;
+  }
   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)) &&
@@ -290,11 +300,13 @@ GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle * h, OFF_T offset,
  *             of all sizes of files in the directory)
  * @param includeSymLinks should symbolic links be
  *        included?
+ * @param singleFileMode GNUNET_YES to only get size of one file
+ *        and return GNUNET_SYSERR for directories.
  * @return GNUNET_SYSERR on error, GNUNET_OK on success
  */
 int
 GNUNET_DISK_file_size (const char *filename, uint64_t * size,
-                       int includeSymLinks)
+                       int includeSymLinks, int singleFileMode)
 {
   struct GetFileSizeData gfsd;
   int ret;
@@ -302,6 +314,7 @@ GNUNET_DISK_file_size (const char *filename, uint64_t * size,
   GNUNET_assert (size != NULL);
   gfsd.total = 0;
   gfsd.include_sym_links = includeSymLinks;
+  gfsd.single_file_mode = singleFileMode;
   ret = getSizeRec (&gfsd, filename);
   *size = gfsd.total;
   return ret;
@@ -1350,7 +1363,7 @@ GNUNET_DISK_file_copy (const char *src, const char *dst)
   struct GNUNET_DISK_FileHandle *in;
   struct GNUNET_DISK_FileHandle *out;
 
-  if (GNUNET_OK != GNUNET_DISK_file_size (src, &size, GNUNET_YES))
+  if (GNUNET_OK != GNUNET_DISK_file_size (src, &size, GNUNET_YES, GNUNET_YES))
     return GNUNET_SYSERR;
   pos = 0;
   in = GNUNET_DISK_file_open (src, GNUNET_DISK_OPEN_READ,
diff --git a/src/util/pseudonym.c b/src/util/pseudonym.c
index c2b9583..d2efdc9 100644
--- a/src/util/pseudonym.c
+++ b/src/util/pseudonym.c
@@ -320,7 +320,7 @@ GNUNET_PSEUDONYM_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg,
 
   len = 0;
   if (0 == STAT (fn, &sbuf))
-    GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (fn, &len, GNUNET_YES));
+    GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES));
   fh = GNUNET_DISK_file_open (fn,
                               GNUNET_DISK_OPEN_CREATE |
                               GNUNET_DISK_OPEN_READWRITE,
@@ -475,7 +475,7 @@ GNUNET_PSEUDONYM_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg,
   GNUNET_assert (fn != NULL);
 
   if ((GNUNET_OK != GNUNET_DISK_file_test (fn) ||
-       (GNUNET_OK != GNUNET_DISK_file_size (fn, &len, GNUNET_YES))) ||
+       (GNUNET_OK != GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES))) ||
       ((idx + 1) * sizeof (GNUNET_HashCode) > len))
   {
     GNUNET_free (fn);
diff --git a/src/util/test_disk.c b/src/util/test_disk.c
index 5462772..149cec0 100644
--- a/src/util/test_disk.c
+++ b/src/util/test_disk.c
@@ -97,7 +97,7 @@ testOpenClose ()
   GNUNET_break (5 == GNUNET_DISK_file_write (fh, "Hello", 5));
   GNUNET_DISK_file_close (fh);
   GNUNET_break (GNUNET_OK ==
-                GNUNET_DISK_file_size (".testfile", &size, GNUNET_NO));
+                GNUNET_DISK_file_size (".testfile", &size, GNUNET_NO, GNUNET_YES));
   if (size != 5)
     return 1;
   GNUNET_break (0 == UNLINK (".testfile"));
-- 
1.7.4

