X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fdisk.c;h=8fd689070aeca4d594f649d86e718fb1653430f2;hb=a3e88087d09186d847ee8bf042ad665ab6cb0850;hp=bef35c89980c1b74020e371a2e680e82bece901b;hpb=2b7a52a080e089e852b0a15da690b058e97bedc0;p=oweals%2Fgnunet.git diff --git a/src/util/disk.c b/src/util/disk.c index bef35c899..8fd689070 100644 --- a/src/util/disk.c +++ b/src/util/disk.c @@ -1,10 +1,10 @@ /* This file is part of GNUnet. - (C) 2001--2012 Christian Grothoff (and other contributing authors) + Copyright (C) 2001--2013, 2016 GNUnet e.V. 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 + by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but @@ -14,70 +14,49 @@ 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. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ - /** * @file util/disk.c * @brief disk IO convenience methods * @author Christian Grothoff * @author Nils Durner */ - #include "platform.h" -#include "gnunet_common.h" -#include "gnunet_directories.h" -#include "gnunet_disk_lib.h" -#include "gnunet_scheduler_lib.h" -#include "gnunet_strings_lib.h" -#include "gnunet_crypto_lib.h" #include "disk.h" +#include "gnunet_strings_lib.h" +#include "gnunet_disk_lib.h" -#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) +#define LOG(kind,...) GNUNET_log_from (kind, "util-disk", __VA_ARGS__) -#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) +#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-disk", syscall) -#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) +#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util-disk", syscall, filename) /** * Block size for IO for copying files. */ #define COPY_BLK_SIZE 65536 - - -#if defined(LINUX) || defined(CYGWIN) || defined(GNU) +#include +#if HAVE_SYS_VFS_H #include -#else -#if defined(SOMEBSD) || defined(DARWIN) +#endif +#if HAVE_SYS_PARAM_H #include +#endif +#if HAVE_SYS_MOUNT_H #include -#else -#ifdef SOLARIS -#include +#endif +#if HAVE_SYS_STATVFS_H #include -#else -#ifdef MINGW -#ifndef PIPE_BUF -#define PIPE_BUF 512 -ULONG PipeSerialNumber; #endif + +#ifndef S_ISLNK #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 - -#if !defined(SOMEBSD) && !defined(DARWIN) && !defined(WINDOWS) -#include -#endif -#if LINUX -#include #endif @@ -159,28 +138,26 @@ translate_unix_perms (enum GNUNET_DISK_AccessPermissions perm) * Iterate over all files in the given directory and * accumulate their size. * - * @param cls closure of type "struct GetFileSizeData" + * @param cls closure of type `struct GetFileSizeData` * @param fn current filename we are looking at - * @return GNUNET_SYSERR on serious errors, otherwise GNUNET_OK + * @return #GNUNET_SYSERR on serious errors, otherwise #GNUNET_OK */ static int getSizeRec (void *cls, const char *fn) { struct GetFileSizeData *gfsd = cls; -#ifdef HAVE_STAT64 - struct stat64 buf; -#else - struct stat buf; -#endif +#if defined (HAVE_STAT64) && !(defined (_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64) + STRUCT_STAT64 buf; -#ifdef HAVE_STAT64 if (0 != STAT64 (fn, &buf)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "stat64", fn); return GNUNET_SYSERR; } #else + struct stat buf; + if (0 != STAT (fn, &buf)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "stat", fn); @@ -208,7 +185,7 @@ getSizeRec (void *cls, const char *fn) * Checks whether a handle is invalid * * @param h handle to check - * @return GNUNET_YES if invalid, GNUNET_NO if valid + * @return #GNUNET_YES if invalid, #GNUNET_NO if valid */ int GNUNET_DISK_handle_invalid (const struct GNUNET_DISK_FileHandle *h) @@ -225,11 +202,11 @@ GNUNET_DISK_handle_invalid (const struct GNUNET_DISK_FileHandle *h) * * @param fh open file handle * @param size where to write size of the file - * @return GNUNET_OK on success, GNUNET_SYSERR on error + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_DISK_file_handle_size (struct GNUNET_DISK_FileHandle *fh, - OFF_T *size) + off_t *size) { #if WINDOWS BOOL b; @@ -240,7 +217,7 @@ GNUNET_DISK_file_handle_size (struct GNUNET_DISK_FileHandle *fh, SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } - *size = (OFF_T) li.QuadPart; + *size = (off_t) li.QuadPart; #else struct stat sbuf; @@ -258,10 +235,10 @@ GNUNET_DISK_file_handle_size (struct GNUNET_DISK_FileHandle *fh, * @param h handle of an open file * @param offset position to move to * @param whence specification to which position the offset parameter relates to - * @return the new position on success, GNUNET_SYSERR otherwise + * @return the new position on success, #GNUNET_SYSERR otherwise */ -OFF_T -GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle * h, OFF_T offset, +off_t +GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle * h, off_t offset, enum GNUNET_DISK_Seek whence) { if (h == NULL) @@ -284,7 +261,7 @@ GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle * h, OFF_T offset, SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } - return (OFF_T) new_pos.QuadPart; + return (off_t) new_pos.QuadPart; #else static int t[] = { SEEK_SET, SEEK_CUR, SEEK_END }; @@ -301,23 +278,25 @@ GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle * h, OFF_T offset, * @param size set to the size of the file (or, * in the case of directories, the sum * of all sizes of files in the directory) - * @param includeSymLinks should symbolic links be + * @param include_symbolic_links 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 + * @param single_file_mode #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 singleFileMode) +GNUNET_DISK_file_size (const char *filename, + uint64_t * size, + int include_symbolic_links, + int single_file_mode) { struct GetFileSizeData gfsd; int ret; GNUNET_assert (size != NULL); gfsd.total = 0; - gfsd.include_sym_links = includeSymLinks; - gfsd.single_file_mode = singleFileMode; + gfsd.include_sym_links = include_symbolic_links; + gfsd.single_file_mode = single_file_mode; ret = getSizeRec (&gfsd, filename); *size = gfsd.total; return ret; @@ -337,55 +316,73 @@ GNUNET_DISK_file_size (const char *filename, uint64_t * size, * @param filename name of the file * @param dev set to the device ID * @param ino set to the inode ID - * @return GNUNET_OK on success + * @return #GNUNET_OK on success */ int GNUNET_DISK_file_get_identifiers (const char *filename, uint64_t * dev, uint64_t * ino) { -#if LINUX - struct stat sbuf; - struct statvfs fbuf; +#if WINDOWS + { + // FIXME NILS: test this + struct GNUNET_DISK_FileHandle *fh; + BY_HANDLE_FILE_INFORMATION info; + int succ; - if ((0 == stat (filename, &sbuf)) && (0 == statvfs (filename, &fbuf))) + fh = GNUNET_DISK_file_open (filename, + GNUNET_DISK_OPEN_READ, + GNUNET_DISK_PERM_NONE); + if (NULL == fh) + return GNUNET_SYSERR; + succ = GetFileInformationByHandle (fh->h, &info); + GNUNET_DISK_file_close (fh); + if (!succ) + { + return GNUNET_SYSERR; + } + *dev = info.dwVolumeSerialNumber; + *ino = ((((uint64_t) info.nFileIndexHigh) << (sizeof (DWORD) * 8)) | info.nFileIndexLow); + } +#else /* !WINDOWS */ +#if HAVE_STAT { - *dev = (uint64_t) fbuf.f_fsid; + struct stat sbuf; + + if (0 != stat (filename, &sbuf)) + { + return GNUNET_SYSERR; + } *ino = (uint64_t) sbuf.st_ino; - return GNUNET_OK; } -#elif SOMEBSD - struct stat sbuf; - struct statfs fbuf; +#else + *ino = 0; +#endif +#if HAVE_STATVFS + { + struct statvfs fbuf; - if ((0 == stat (filename, &sbuf)) && (0 == statfs (filename, &fbuf))) + if (0 != statvfs (filename, &fbuf)) + { + return GNUNET_SYSERR; + } + *dev = (uint64_t) fbuf.f_fsid; + } +#elif HAVE_STATFS { + struct statfs fbuf; + + if (0 != statfs (filename, &fbuf)) + { + return GNUNET_SYSERR; + } *dev = ((uint64_t) fbuf.f_fsid.val[0]) << 32 || ((uint64_t) fbuf.f_fsid.val[1]); - *ino = (uint64_t) sbuf.st_ino; - return GNUNET_OK; } -#elif WINDOWS - // FIXME NILS: test this - struct GNUNET_DISK_FileHandle *fh; - BY_HANDLE_FILE_INFORMATION info; - int succ; - - fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, 0); - if (fh == NULL) - return GNUNET_SYSERR; - succ = GetFileInformationByHandle (fh->h, &info); - GNUNET_DISK_file_close (fh); - if (succ) - { - *dev = info.dwVolumeSerialNumber; - *ino = ((((uint64_t) info.nFileIndexHigh) << (sizeof (DWORD) * 8)) | info.nFileIndexLow); - return GNUNET_OK; - } - else - return GNUNET_SYSERR; - +#else + *dev = 0; #endif - return GNUNET_SYSERR; +#endif /* !WINDOWS */ + return GNUNET_OK; } @@ -413,7 +410,7 @@ mktemp_name (const char *t) if (NULL == tmpdir) tmpdir = getenv ("TMP"); if (NULL == tmpdir) - tmpdir = getenv ("TEMP"); + tmpdir = getenv ("TEMP"); if (NULL == tmpdir) tmpdir = "/tmp"; GNUNET_asprintf (&tmpl, "%s/%s%s", tmpdir, t, "XXXXXX"); @@ -468,6 +465,53 @@ mkdtemp (char *fn) strcpy (fn, tfn); return fn; } + +/** + * Update POSIX permissions mask of a file on disk. If both argumets + * are #GNUNET_NO, the file is made world-read-write-executable (777). + * Does nothing on W32. + * + * @param fn name of the file to update + * @param require_uid_match #GNUNET_YES means 700 + * @param require_gid_match #GNUNET_YES means 770 unless @a require_uid_match is set + */ +void +GNUNET_DISK_fix_permissions (const char *fn, + int require_uid_match, + int require_gid_match) +{ + /* nothing on W32 */ +} + +#else + +/** + * Update POSIX permissions mask of a file on disk. If both argumets + * are #GNUNET_NO, the file is made world-read-write-executable (777). + * + * @param fn name of the file to update + * @param require_uid_match #GNUNET_YES means 700 + * @param require_gid_match #GNUNET_YES means 770 unless @a require_uid_match is set + */ +void +GNUNET_DISK_fix_permissions (const char *fn, + int require_uid_match, + int require_gid_match) +{ + mode_t mode; + + if (GNUNET_YES == require_uid_match) + mode = S_IRUSR | S_IWUSR | S_IXUSR; + else if (GNUNET_YES == require_gid_match) + mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP; + else + mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH; + if (0 != chmod (fn, mode)) + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, + "chmod", + fn); +} + #endif /** @@ -485,14 +529,18 @@ char * GNUNET_DISK_mkdtemp (const char *t) { char *fn; + mode_t omask; + omask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH); fn = mktemp_name (t); if (fn != mkdtemp (fn)) { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "mkstemp", fn); + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "mkdtemp", fn); GNUNET_free (fn); + umask (omask); return NULL; } + umask (omask); return fn; } @@ -525,7 +573,7 @@ GNUNET_DISK_file_backup (const char *fil) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "rename", fil); - GNUNET_free (target); + GNUNET_free (target); } @@ -545,14 +593,18 @@ GNUNET_DISK_mktemp (const char *t) { int fd; char *fn; + mode_t omask; + omask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH); fn = mktemp_name (t); if (-1 == (fd = mkstemp (fn))) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "mkstemp", fn); GNUNET_free (fn); + umask (omask); return NULL; } + umask (omask); if (0 != CLOSE (fd)) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "close", fn); return fn; @@ -560,74 +612,15 @@ GNUNET_DISK_mktemp (const char *t) /** - * 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 - */ -long -GNUNET_DISK_get_blocks_available (const char *part) -{ -#ifdef SOLARIS - struct statvfs buf; - - if (0 != statvfs (part, &buf)) - { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "statfs", part); - return -1; - } - return buf.f_bavail; -#elif MINGW - DWORD dwDummy; - DWORD dwBlocks; - wchar_t szDrive[4]; - wchar_t wpath[MAX_PATH + 1]; - char *path; - - path = GNUNET_STRINGS_filename_expand (part); - if (path == NULL) - return -1; - /* "part" was in UTF-8, and so is "path" */ - if (ERROR_SUCCESS != plibc_conv_to_win_pathwconv(path, wpath)) - { - GNUNET_free (path); - return -1; - } - GNUNET_free (path); - wcsncpy (szDrive, wpath, 3); - szDrive[3] = 0; - if (!GetDiskFreeSpaceW (szDrive, &dwDummy, &dwDummy, &dwBlocks, &dwDummy)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, _("`%s' failed for drive `%S': %u\n"), - "GetDiskFreeSpace", szDrive, GetLastError ()); - - return -1; - } - return dwBlocks; -#else - struct statfs s; - - if (0 != statfs (part, &s)) - { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "statfs", part); - return -1; - } - return s.f_bavail; -#endif -} - - -/** - * Test if "fil" is a directory and listable. Optionally, also check if the + * Test if @a fil is a directory and listable. Optionally, also check if the * directory is readable. Will not print an error message if the directory does - * not exist. Will log errors if GNUNET_SYSERR is returned (i.e., a file exists + * not exist. Will log errors if #GNUNET_SYSERR is returned (i.e., a file exists * with the same name). * * @param fil filename to test - * @param is_readable GNUNET_YES to additionally check if "fil" is readable; - * GNUNET_NO to disable this check - * @return GNUNET_YES if yes, GNUNET_NO if not; GNUNET_SYSERR if it + * @param is_readable #GNUNET_YES to additionally check if @a fil is readable; + * #GNUNET_NO to disable this check + * @return #GNUNET_YES if yes, #GNUNET_NO if not; #GNUNET_SYSERR if it * does not exist or stat'ed */ int @@ -645,7 +638,7 @@ GNUNET_DISK_directory_test (const char *fil, int is_readable) } if (!S_ISDIR (filestat.st_mode)) { - LOG (GNUNET_ERROR_TYPE_WARNING, + LOG (GNUNET_ERROR_TYPE_DEBUG, "A file already exits with the same name %s\n", fil); return GNUNET_NO; } @@ -667,7 +660,7 @@ GNUNET_DISK_directory_test (const char *fil, int is_readable) * (of a file that exists and that is not a directory). * * @param fil filename to check - * @return GNUNET_YES if yes, GNUNET_NO if not a file, GNUNET_SYSERR if something + * @return #GNUNET_YES if yes, #GNUNET_NO if not a file, #GNUNET_SYSERR if something * else (will print an error message in that case, too). */ int @@ -711,8 +704,9 @@ GNUNET_DISK_file_test (const char *fil) /** * Implementation of "mkdir -p" + * * @param dir the directory to create - * @returns GNUNET_OK on success, GNUNET_SYSERR on failure + * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_DISK_directory_create (const char *dir) @@ -816,81 +810,100 @@ GNUNET_DISK_directory_create (const char *dir) /** - * Create the directory structure for storing - * a file. + * Create the directory structure for storing a file. * * @param filename name of a file in the directory - * @returns GNUNET_OK on success, - * GNUNET_SYSERR on failure, - * GNUNET_NO if the directory + * @returns #GNUNET_OK on success, + * #GNUNET_SYSERR on failure, + * #GNUNET_NO if the directory * exists but is not writeable for us */ int GNUNET_DISK_directory_create_for_file (const char *filename) { char *rdir; - int len; + size_t len; int ret; + int eno; rdir = GNUNET_STRINGS_filename_expand (filename); - if (rdir == NULL) + if (NULL == rdir) + { + errno = EINVAL; return GNUNET_SYSERR; + } len = strlen (rdir); while ((len > 0) && (rdir[len] != DIR_SEPARATOR)) len--; rdir[len] = '\0'; + /* The empty path is invalid and in this case refers to / */ + if (0 == len) + { + GNUNET_free (rdir); + rdir = GNUNET_strdup ("/"); + } ret = GNUNET_DISK_directory_create (rdir); - if ((ret == GNUNET_OK) && (0 != ACCESS (rdir, W_OK))) + if ((GNUNET_OK == ret) && (0 != ACCESS (rdir, W_OK))) ret = GNUNET_NO; + eno = errno; GNUNET_free (rdir); + errno = eno; return ret; } /** * Read the contents of a binary file into a buffer. + * * @param h handle to an open file * @param result the buffer to write the result to * @param len the maximum number of bytes to read - * @return the number of bytes read on success, GNUNET_SYSERR on failure + * @return the number of bytes read on success, #GNUNET_SYSERR on failure */ ssize_t -GNUNET_DISK_file_read (const struct GNUNET_DISK_FileHandle * h, void *result, +GNUNET_DISK_file_read (const struct GNUNET_DISK_FileHandle *h, + void *result, size_t len) { - if (h == NULL) + if (NULL == h) { errno = EINVAL; return GNUNET_SYSERR; } #ifdef MINGW - DWORD bytesRead; + DWORD bytes_read; - if (h->type != GNUNET_DISK_HANLDE_TYPE_PIPE) + if (h->type == GNUNET_DISK_HANLDE_TYPE_FILE) { - if (!ReadFile (h->h, result, len, &bytesRead, NULL)) + if (!ReadFile (h->h, result, len, &bytes_read, NULL)) { SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } } - else + else if (h->type == GNUNET_DISK_HANLDE_TYPE_PIPE) { - if (!ReadFile (h->h, result, len, &bytesRead, h->oOverlapRead)) + if (!ReadFile (h->h, result, len, &bytes_read, h->oOverlapRead)) { if (GetLastError () != ERROR_IO_PENDING) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Error reading from pipe: %u\n", GetLastError ()); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Error reading from pipe: %u\n", + GetLastError ()); SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Will get overlapped result\n"); - GetOverlappedResult (h->h, h->oOverlapRead, &bytesRead, TRUE); + GetOverlappedResult (h->h, h->oOverlapRead, &bytes_read, TRUE); } - LOG (GNUNET_ERROR_TYPE_DEBUG, "Read %u bytes from pipe\n", bytesRead); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Read %u bytes from pipe\n", bytes_read); + } + else + { + bytes_read = 0; } - return bytesRead; + return bytes_read; #else return read (h->fd, result, len); #endif @@ -905,33 +918,33 @@ GNUNET_DISK_file_read (const struct GNUNET_DISK_FileHandle * h, void *result, * @param h handle to an open file * @param result the buffer to write the result to * @param len the maximum number of bytes to read - * @return the number of bytes read on success, GNUNET_SYSERR on failure + * @return the number of bytes read on success, #GNUNET_SYSERR on failure */ ssize_t -GNUNET_DISK_file_read_non_blocking (const struct GNUNET_DISK_FileHandle * h, - void *result, +GNUNET_DISK_file_read_non_blocking (const struct GNUNET_DISK_FileHandle *h, + void *result, size_t len) { - if (h == NULL) + if (NULL == h) { errno = EINVAL; return GNUNET_SYSERR; } #ifdef MINGW - DWORD bytesRead; + DWORD bytes_read; - if (h->type != GNUNET_DISK_HANLDE_TYPE_PIPE) + if (h->type == GNUNET_DISK_HANLDE_TYPE_FILE) { - if (!ReadFile (h->h, result, len, &bytesRead, NULL)) + if (!ReadFile (h->h, result, len, &bytes_read, NULL)) { SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } } - else + else if (h->type == GNUNET_DISK_HANLDE_TYPE_PIPE) { - if (!ReadFile (h->h, result, len, &bytesRead, h->oOverlapRead)) + if (!ReadFile (h->h, result, len, &bytes_read, h->oOverlapRead)) { if (GetLastError () != ERROR_IO_PENDING) { @@ -948,9 +961,15 @@ GNUNET_DISK_file_read_non_blocking (const struct GNUNET_DISK_FileHandle * h, return GNUNET_SYSERR; } } - LOG (GNUNET_ERROR_TYPE_DEBUG, "Read %u bytes\n", bytesRead); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Read %u bytes\n", + bytes_read); + } + else + { + bytes_read = 0; } - return bytesRead; + return bytes_read; #else int flags; ssize_t ret; @@ -977,56 +996,63 @@ GNUNET_DISK_file_read_non_blocking (const struct GNUNET_DISK_FileHandle * h, * @param fn file name * @param result the buffer to write the result to * @param len the maximum number of bytes to read - * @return number of bytes read, GNUNET_SYSERR on failure + * @return number of bytes read, #GNUNET_SYSERR on failure */ ssize_t -GNUNET_DISK_fn_read (const char *fn, void *result, size_t len) +GNUNET_DISK_fn_read (const char *fn, + void *result, + size_t len) { struct GNUNET_DISK_FileHandle *fh; ssize_t ret; + int eno; - fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); - if (!fh) + fh = GNUNET_DISK_file_open (fn, + GNUNET_DISK_OPEN_READ, + GNUNET_DISK_PERM_NONE); + if (NULL == fh) return GNUNET_SYSERR; ret = GNUNET_DISK_file_read (fh, result, len); + eno = errno; GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); - + errno = eno; return ret; } /** * Write a buffer to a file. + * * @param h handle to open file * @param buffer the data to write * @param n number of bytes to write - * @return number of bytes written on success, GNUNET_SYSERR on error + * @return number of bytes written on success, #GNUNET_SYSERR on error */ ssize_t GNUNET_DISK_file_write (const struct GNUNET_DISK_FileHandle * h, const void *buffer, size_t n) { - if (h == NULL) + if (NULL == h) { errno = EINVAL; return GNUNET_SYSERR; } #ifdef MINGW - DWORD bytesWritten; + DWORD bytes_written; - if (h->type != GNUNET_DISK_HANLDE_TYPE_PIPE) + if (h->type == GNUNET_DISK_HANLDE_TYPE_FILE) { - if (!WriteFile (h->h, buffer, n, &bytesWritten, NULL)) + if (!WriteFile (h->h, buffer, n, &bytes_written, NULL)) { SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } } - else + else if (h->type == GNUNET_DISK_HANLDE_TYPE_PIPE) { LOG (GNUNET_ERROR_TYPE_DEBUG, "It is a pipe trying to write %u bytes\n", n); - if (!WriteFile (h->h, buffer, n, &bytesWritten, h->oOverlapWrite)) + if (!WriteFile (h->h, buffer, n, &bytes_written, h->oOverlapWrite)) { if (GetLastError () != ERROR_IO_PENDING) { @@ -1036,7 +1062,7 @@ GNUNET_DISK_file_write (const struct GNUNET_DISK_FileHandle * h, return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Will get overlapped result\n"); - if (!GetOverlappedResult (h->h, h->oOverlapWrite, &bytesWritten, TRUE)) + if (!GetOverlappedResult (h->h, h->oOverlapWrite, &bytes_written, TRUE)) { SetErrnoFromWinError (GetLastError ()); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1058,21 +1084,25 @@ GNUNET_DISK_file_write (const struct GNUNET_DISK_FileHandle * h, { LOG (GNUNET_ERROR_TYPE_DEBUG, "Wrote %u bytes (ovr says %u), picking the greatest\n", - bytesWritten, ovr); + bytes_written, ovr); } } - if (bytesWritten == 0) + if (bytes_written == 0) { if (n > 0) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Wrote %u bytes, returning -1 with EAGAIN\n", bytesWritten); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Wrote %u bytes, returning -1 with EAGAIN\n", bytes_written); errno = EAGAIN; return GNUNET_SYSERR; } } - LOG (GNUNET_ERROR_TYPE_DEBUG, "Wrote %u bytes\n", bytesWritten); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Wrote %u bytes\n", bytes_written); } - return bytesWritten; + else + { + bytes_written = 0; + } + return bytes_written; #else return write (h->fd, buffer, n); #endif @@ -1081,37 +1111,39 @@ GNUNET_DISK_file_write (const struct GNUNET_DISK_FileHandle * h, /** * Write a buffer to a file, blocking, if necessary. + * * @param h handle to open file * @param buffer the data to write * @param n number of bytes to write - * @return number of bytes written on success, GNUNET_SYSERR on error + * @return number of bytes written on success, #GNUNET_SYSERR on error */ ssize_t GNUNET_DISK_file_write_blocking (const struct GNUNET_DISK_FileHandle * h, - const void *buffer, size_t n) + const void *buffer, + size_t n) { - if (h == NULL) + if (NULL == h) { errno = EINVAL; return GNUNET_SYSERR; } #ifdef MINGW - DWORD bytesWritten; + DWORD bytes_written; /* We do a non-overlapped write, which is as blocking as it gets */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Writing %u bytes\n", n); - if (!WriteFile (h->h, buffer, n, &bytesWritten, NULL)) + if (!WriteFile (h->h, buffer, n, &bytes_written, NULL)) { SetErrnoFromWinError (GetLastError ()); LOG (GNUNET_ERROR_TYPE_DEBUG, "Error writing to pipe: %u\n", GetLastError ()); return GNUNET_SYSERR; } - if (bytesWritten == 0 && n > 0) + if (bytes_written == 0 && n > 0) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Waiting for pipe to clean\n"); WaitForSingleObject (h->h, INFINITE); - if (!WriteFile (h->h, buffer, n, &bytesWritten, NULL)) + if (!WriteFile (h->h, buffer, n, &bytes_written, NULL)) { SetErrnoFromWinError (GetLastError ()); LOG (GNUNET_ERROR_TYPE_DEBUG, "Error writing to pipe: %u\n", @@ -1119,8 +1151,10 @@ GNUNET_DISK_file_write_blocking (const struct GNUNET_DISK_FileHandle * h, return GNUNET_SYSERR; } } - LOG (GNUNET_ERROR_TYPE_DEBUG, "Wrote %u bytes\n", bytesWritten); - return bytesWritten; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Wrote %u bytes\n", + bytes_written); + return bytes_written; #else int flags; ssize_t ret; @@ -1145,10 +1179,12 @@ GNUNET_DISK_file_write_blocking (const struct GNUNET_DISK_FileHandle * h, * @param buffer the data to write * @param n number of bytes to write * @param mode file permissions - * @return number of bytes written on success, GNUNET_SYSERR on error + * @return number of bytes written on success, #GNUNET_SYSERR on error */ ssize_t -GNUNET_DISK_fn_write (const char *fn, const void *buffer, size_t n, +GNUNET_DISK_fn_write (const char *fn, + const void *buffer, + size_t n, enum GNUNET_DISK_AccessPermissions mode) { struct GNUNET_DISK_FileHandle *fh; @@ -1157,7 +1193,7 @@ GNUNET_DISK_fn_write (const char *fn, const void *buffer, size_t n, fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_TRUNCATE | GNUNET_DISK_OPEN_CREATE, mode); - if (!fh) + if (! fh) return GNUNET_SYSERR; ret = GNUNET_DISK_file_write (fh, buffer, n); GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); @@ -1168,15 +1204,15 @@ GNUNET_DISK_fn_write (const char *fn, const void *buffer, size_t n, /** * Scan a directory for files. * - * @param dirName the name of the directory + * @param dir_name the name of the directory * @param callback the method to call for each file, * can be NULL, in that case, we only count - * @param callback_cls closure for callback - * @return the number of files found, GNUNET_SYSERR on error or - * ieration aborted by callback returning GNUNET_SYSERR + * @param callback_cls closure for @a callback + * @return the number of files found, #GNUNET_SYSERR on error or + * ieration aborted by callback returning #GNUNET_SYSERR */ int -GNUNET_DISK_directory_scan (const char *dirName, +GNUNET_DISK_directory_scan (const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls) { @@ -1184,68 +1220,86 @@ GNUNET_DISK_directory_scan (const char *dirName, struct dirent *finfo; struct stat istat; int count = 0; + int ret; char *name; char *dname; unsigned int name_len; unsigned int n_size; - GNUNET_assert (dirName != NULL); - dname = GNUNET_STRINGS_filename_expand (dirName); - if (dname == NULL) + GNUNET_assert (NULL != dir_name); + dname = GNUNET_STRINGS_filename_expand (dir_name); + if (NULL == dname) return GNUNET_SYSERR; - while ((strlen (dname) > 0) && (dname[strlen (dname) - 1] == DIR_SEPARATOR)) + while ( (strlen (dname) > 0) && + (dname[strlen (dname) - 1] == DIR_SEPARATOR) ) dname[strlen (dname) - 1] = '\0'; if (0 != STAT (dname, &istat)) { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", dname); + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, + "stat", + dname); GNUNET_free (dname); return GNUNET_SYSERR; } - if (!S_ISDIR (istat.st_mode)) + if (! S_ISDIR (istat.st_mode)) { - LOG (GNUNET_ERROR_TYPE_WARNING, _("Expected `%s' to be a directory!\n"), - dirName); + LOG (GNUNET_ERROR_TYPE_WARNING, + _("Expected `%s' to be a directory!\n"), + dir_name); GNUNET_free (dname); return GNUNET_SYSERR; } errno = 0; dinfo = OPENDIR (dname); - if ((errno == EACCES) || (dinfo == NULL)) + if ( (EACCES == errno) || + (NULL == dinfo) ) { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "opendir", dname); - if (dinfo != NULL) + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, + "opendir", + dname); + if (NULL != dinfo) CLOSEDIR (dinfo); GNUNET_free (dname); return GNUNET_SYSERR; } name_len = 256; - n_size = strlen (dname) + name_len + 2; + n_size = strlen (dname) + name_len + strlen (DIR_SEPARATOR_STR) + 1; name = GNUNET_malloc (n_size); - while ((finfo = READDIR (dinfo)) != NULL) + while (NULL != (finfo = READDIR (dinfo))) { - if ((0 == strcmp (finfo->d_name, ".")) || - (0 == strcmp (finfo->d_name, ".."))) + if ( (0 == strcmp (finfo->d_name, ".")) || + (0 == strcmp (finfo->d_name, "..")) ) continue; - if (callback != NULL) + if (NULL != callback) { if (name_len < strlen (finfo->d_name)) { GNUNET_free (name); name_len = strlen (finfo->d_name); - n_size = strlen (dname) + name_len + 2; + n_size = strlen (dname) + name_len + strlen (DIR_SEPARATOR_STR) + 1; name = GNUNET_malloc (n_size); } /* dname can end in "/" only if dname == "/"; * if dname does not end in "/", we need to add * a "/" (otherwise, we must not!) */ - GNUNET_snprintf (name, n_size, "%s%s%s", dname, - (strcmp (dname, DIR_SEPARATOR_STR) == - 0) ? "" : DIR_SEPARATOR_STR, finfo->d_name); - if (GNUNET_OK != callback (callback_cls, name)) + GNUNET_snprintf (name, + n_size, + "%s%s%s", + dname, + (0 == strcmp (dname, + DIR_SEPARATOR_STR)) + ? "" + : DIR_SEPARATOR_STR, + finfo->d_name); + ret = callback (callback_cls, + name); + if (GNUNET_OK != ret) { CLOSEDIR (dinfo); GNUNET_free (name); GNUNET_free (dname); + if (GNUNET_NO == ret) + return count; return GNUNET_SYSERR; } } @@ -1258,194 +1312,70 @@ GNUNET_DISK_directory_scan (const char *dirName, } -/** - * Opaque handle used for iterating over a directory. - */ -struct GNUNET_DISK_DirectoryIterator -{ - - /** - * Function to call on directory entries. - */ - GNUNET_DISK_DirectoryIteratorCallback callback; - - /** - * Closure for callback. - */ - void *callback_cls; - - /** - * Reference to directory. - */ - DIR *directory; - - /** - * Directory name. - */ - char *dirname; - - /** - * Next filename to process. - */ - char *next_name; - - /** - * Our priority. - */ - enum GNUNET_SCHEDULER_Priority priority; - -}; - - -/** - * Task used by the directory iterator. - */ -static void -directory_iterator_task (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_DISK_DirectoryIterator *iter = cls; - char *name; - - name = iter->next_name; - GNUNET_assert (name != NULL); - iter->next_name = NULL; - iter->callback (iter->callback_cls, iter, name, iter->dirname); - GNUNET_free (name); -} - - -/** - * This function must be called during the DiskIteratorCallback - * (exactly once) to schedule the task to process the next - * filename in the directory (if there is one). - * - * @param iter opaque handle for the iterator - * @param can set to GNUNET_YES to terminate the iteration early - * @return GNUNET_YES if iteration will continue, - * GNUNET_NO if this was the last entry (and iteration is complete), - * GNUNET_SYSERR if abort was YES - */ -int -GNUNET_DISK_directory_iterator_next (struct GNUNET_DISK_DirectoryIterator *iter, - int can) -{ - struct dirent *finfo; - - GNUNET_assert (iter->next_name == NULL); - if (can == GNUNET_YES) - { - CLOSEDIR (iter->directory); - GNUNET_free (iter->dirname); - GNUNET_free (iter); - return GNUNET_SYSERR; - } - while (NULL != (finfo = READDIR (iter->directory))) - { - if ((0 == strcmp (finfo->d_name, ".")) || - (0 == strcmp (finfo->d_name, ".."))) - continue; - GNUNET_asprintf (&iter->next_name, "%s%s%s", iter->dirname, - DIR_SEPARATOR_STR, finfo->d_name); - break; - } - if (finfo == NULL) - { - GNUNET_DISK_directory_iterator_next (iter, GNUNET_YES); - return GNUNET_NO; - } - GNUNET_SCHEDULER_add_with_priority (iter->priority, &directory_iterator_task, - iter); - return GNUNET_YES; -} - - -/** - * Scan a directory for files using the scheduler to run a task for - * each entry. The name of the directory must be expanded first (!). - * If a scheduler does not need to be used, GNUNET_DISK_directory_scan - * may provide a simpler API. - * - * @param prio priority to use - * @param dirName the name of the directory - * @param callback the method to call for each file - * @param callback_cls closure for callback - * @return GNUNET_YES if directory is not empty and 'callback' - * will be called later, GNUNET_NO otherwise, GNUNET_SYSERR on error. - */ -int -GNUNET_DISK_directory_iterator_start (enum GNUNET_SCHEDULER_Priority prio, - const char *dirName, - GNUNET_DISK_DirectoryIteratorCallback - callback, void *callback_cls) -{ - struct GNUNET_DISK_DirectoryIterator *di; - - di = GNUNET_malloc (sizeof (struct GNUNET_DISK_DirectoryIterator)); - di->callback = callback; - di->callback_cls = callback_cls; - di->directory = OPENDIR (dirName); - if (di->directory == NULL) - { - GNUNET_free (di); - callback (callback_cls, NULL, NULL, NULL); - return GNUNET_SYSERR; - } - di->dirname = GNUNET_strdup (dirName); - di->priority = prio; - return GNUNET_DISK_directory_iterator_next (di, GNUNET_NO); -} - - /** * Function that removes the given directory by calling - * "GNUNET_DISK_directory_remove". + * #GNUNET_DISK_directory_remove(). * * @param unused not used * @param fn directory to remove - * @return GNUNET_OK + * @return #GNUNET_OK */ static int -remove_helper (void *unused, const char *fn) +remove_helper (void *unused, + const char *fn) { + (void) unused; (void) GNUNET_DISK_directory_remove (fn); return GNUNET_OK; } /** - * Remove all files in a directory (rm -rf). Call with + * Remove all files in a directory (rm -r). Call with * caution. * - * * @param filename the file to remove - * @return GNUNET_OK on success, GNUNET_SYSERR on error + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_DISK_directory_remove (const char *filename) { struct stat istat; + if (NULL == filename) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } if (0 != LSTAT (filename, &istat)) return GNUNET_NO; /* file may not exist... */ - (void) CHMOD (filename, S_IWUSR | S_IRUSR | S_IXUSR); - if (UNLINK (filename) == 0) + (void) CHMOD (filename, + S_IWUSR | S_IRUSR | S_IXUSR); + if (0 == UNLINK (filename)) return GNUNET_OK; - if ((errno != EISDIR) && - /* EISDIR is not sufficient in all cases, e.g. - * sticky /tmp directory may result in EPERM on BSD. - * So we also explicitly check "isDirectory" */ - (GNUNET_YES != GNUNET_DISK_directory_test (filename, GNUNET_YES))) - { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "rmdir", filename); + if ( (errno != EISDIR) && + /* EISDIR is not sufficient in all cases, e.g. + * sticky /tmp directory may result in EPERM on BSD. + * So we also explicitly check "isDirectory" */ + (GNUNET_YES != + GNUNET_DISK_directory_test (filename, + GNUNET_YES)) ) + { + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, + "rmdir", + filename); return GNUNET_SYSERR; } if (GNUNET_SYSERR == - GNUNET_DISK_directory_scan (filename, &remove_helper, NULL)) + GNUNET_DISK_directory_scan (filename, + &remove_helper, + NULL)) return GNUNET_SYSERR; if (0 != RMDIR (filename)) { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "rmdir", filename); + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, + "rmdir", + filename); return GNUNET_SYSERR; } return GNUNET_OK; @@ -1457,15 +1387,17 @@ GNUNET_DISK_directory_remove (const char *filename) * * @param src file to copy * @param dst destination file name - * @return GNUNET_OK on success, GNUNET_SYSERR on error + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int -GNUNET_DISK_file_copy (const char *src, const char *dst) +GNUNET_DISK_file_copy (const char *src, + const char *dst) { char *buf; uint64_t pos; uint64_t size; size_t len; + ssize_t sret; struct GNUNET_DISK_FileHandle *in; struct GNUNET_DISK_FileHandle *out; @@ -1495,9 +1427,17 @@ GNUNET_DISK_file_copy (const char *src, const char *dst) len = COPY_BLK_SIZE; if (len > size - pos) len = size - pos; - if (len != GNUNET_DISK_file_read (in, buf, len)) + sret = GNUNET_DISK_file_read (in, + buf, + len); + if ( (sret < 0) || + (len != (size_t) sret) ) goto FAIL; - if (len != GNUNET_DISK_file_write (out, buf, len)) + sret = GNUNET_DISK_file_write (out, + buf, + len); + if ( (sret < 0) || + (len != (size_t) sret) ) goto FAIL; pos += len; } @@ -1523,18 +1463,16 @@ GNUNET_DISK_filename_canonicalize (char *fn) char *idx; char c; - idx = fn; - while (*idx) + for (idx = fn; *idx; idx++) { c = *idx; - if (c == '/' || c == '\\' || c == ':' || c == '*' || c == '?' || c == '"' || + if (c == '/' || c == '\\' || c == ':' || + c == '*' || c == '?' || c == '"' || c == '<' || c == '>' || c == '|') { *idx = '_'; } - - idx++; } } @@ -1545,24 +1483,33 @@ GNUNET_DISK_filename_canonicalize (char *fn) * * @param filename name of file to change the owner of * @param user name of the new owner - * @return GNUNET_OK on success, GNUNET_SYSERR on failure + * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int -GNUNET_DISK_file_change_owner (const char *filename, const char *user) +GNUNET_DISK_file_change_owner (const char *filename, + const char *user) { #ifndef MINGW struct passwd *pws; pws = getpwnam (user); - if (pws == NULL) + if (NULL == pws) { LOG (GNUNET_ERROR_TYPE_ERROR, - _("Cannot obtain information about user `%s': %s\n"), user, + _("Cannot obtain information about user `%s': %s\n"), + user, STRERROR (errno)); return GNUNET_SYSERR; } - if (0 != chown (filename, pws->pw_uid, pws->pw_gid)) - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "chown", filename); + if (0 != chown (filename, + pws->pw_uid, + pws->pw_gid)) + { + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, + "chown", + filename); + return GNUNET_SYSERR; + } #endif return GNUNET_OK; } @@ -1570,15 +1517,18 @@ GNUNET_DISK_file_change_owner (const char *filename, const char *user) /** * Lock a part of a file + * * @param fh file handle - * @param lockStart absolute position from where to lock - * @param lockEnd absolute position until where to lock - * @param excl GNUNET_YES for an exclusive lock - * @return GNUNET_OK on success, GNUNET_SYSERR on error + * @param lock_start absolute position from where to lock + * @param lock_end absolute position until where to lock + * @param excl #GNUNET_YES for an exclusive lock + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int -GNUNET_DISK_file_lock (struct GNUNET_DISK_FileHandle *fh, OFF_T lockStart, - OFF_T lockEnd, int excl) +GNUNET_DISK_file_lock (struct GNUNET_DISK_FileHandle *fh, + off_t lock_start, + off_t lock_end, + int excl) { if (fh == NULL) { @@ -1592,20 +1542,20 @@ GNUNET_DISK_file_lock (struct GNUNET_DISK_FileHandle *fh, OFF_T lockStart, memset (&fl, 0, sizeof (struct flock)); fl.l_type = excl ? F_WRLCK : F_RDLCK; fl.l_whence = SEEK_SET; - fl.l_start = lockStart; - fl.l_len = lockEnd; + fl.l_start = lock_start; + fl.l_len = lock_end; return fcntl (fh->fd, F_SETLK, &fl) != 0 ? GNUNET_SYSERR : GNUNET_OK; #else OVERLAPPED o; - OFF_T diff = lockEnd - lockStart; + off_t diff = lock_end - lock_start; DWORD diff_low, diff_high; diff_low = (DWORD) (diff & 0xFFFFFFFF); diff_high = (DWORD) ((diff >> (sizeof (DWORD) * 8)) & 0xFFFFFFFF); memset (&o, 0, sizeof (OVERLAPPED)); - o.Offset = (DWORD) (lockStart & 0xFFFFFFFF);; - o.OffsetHigh = (DWORD) (((lockStart & ~0xFFFFFFFF) >> (sizeof (DWORD) * 8)) & 0xFFFFFFFF); + o.Offset = (DWORD) (lock_start & 0xFFFFFFFF);; + o.OffsetHigh = (DWORD) (((lock_start & ~0xFFFFFFFF) >> (sizeof (DWORD) * 8)) & 0xFFFFFFFF); if (!LockFileEx (fh->h, (excl ? LOCKFILE_EXCLUSIVE_LOCK : 0) | LOCKFILE_FAIL_IMMEDIATELY, @@ -1622,14 +1572,16 @@ GNUNET_DISK_file_lock (struct GNUNET_DISK_FileHandle *fh, OFF_T lockStart, /** * Unlock a part of a file + * * @param fh file handle - * @param unlockStart absolute position from where to unlock - * @param unlockEnd absolute position until where to unlock - * @return GNUNET_OK on success, GNUNET_SYSERR on error + * @param unlock_start absolute position from where to unlock + * @param unlock_end absolute position until where to unlock + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int -GNUNET_DISK_file_unlock (struct GNUNET_DISK_FileHandle *fh, OFF_T unlockStart, - OFF_T unlockEnd) +GNUNET_DISK_file_unlock (struct GNUNET_DISK_FileHandle *fh, + off_t unlock_start, + off_t unlock_end) { if (fh == NULL) { @@ -1643,20 +1595,20 @@ GNUNET_DISK_file_unlock (struct GNUNET_DISK_FileHandle *fh, OFF_T unlockStart, memset (&fl, 0, sizeof (struct flock)); fl.l_type = F_UNLCK; fl.l_whence = SEEK_SET; - fl.l_start = unlockStart; - fl.l_len = unlockEnd; + fl.l_start = unlock_start; + fl.l_len = unlock_end; return fcntl (fh->fd, F_SETLK, &fl) != 0 ? GNUNET_SYSERR : GNUNET_OK; #else OVERLAPPED o; - OFF_T diff = unlockEnd - unlockStart; + off_t diff = unlock_end - unlock_start; DWORD diff_low, diff_high; diff_low = (DWORD) (diff & 0xFFFFFFFF); diff_high = (DWORD) ((diff >> (sizeof (DWORD) * 8)) & 0xFFFFFFFF); memset (&o, 0, sizeof (OVERLAPPED)); - o.Offset = (DWORD) (unlockStart & 0xFFFFFFFF);; - o.OffsetHigh = (DWORD) (((unlockStart & ~0xFFFFFFFF) >> (sizeof (DWORD) * 8)) & 0xFFFFFFFF); + o.Offset = (DWORD) (unlock_start & 0xFFFFFFFF);; + o.OffsetHigh = (DWORD) (((unlock_start & ~0xFFFFFFFF) >> (sizeof (DWORD) * 8)) & 0xFFFFFFFF); if (!UnlockFileEx (fh->h, 0, diff_low, diff_high, &o)) { @@ -1677,12 +1629,13 @@ GNUNET_DISK_file_unlock (struct GNUNET_DISK_FileHandle *fh, OFF_T unlockStart, * @param fn file name to be opened * @param flags opening flags, a combination of GNUNET_DISK_OPEN_xxx bit flags * @param perm permissions for the newly created file, use - * GNUNET_DISK_PERM_USER_NONE if a file could not be created by this + * #GNUNET_DISK_PERM_NONE if a file could not be created by this * call (because of flags) * @return IO handle on success, NULL on error */ struct GNUNET_DISK_FileHandle * -GNUNET_DISK_file_open (const char *fn, enum GNUNET_DISK_OpenFlags flags, +GNUNET_DISK_file_open (const char *fn, + enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm) { char *expfn; @@ -1729,7 +1682,7 @@ GNUNET_DISK_file_open (const char *fn, enum GNUNET_DISK_OpenFlags flags, mode = translate_unix_perms (perm); } - fd = open (expfn, oflags + fd = open (expfn, oflags #if O_CLOEXEC | O_CLOEXEC #endif @@ -1803,7 +1756,7 @@ GNUNET_DISK_file_open (const char *fn, enum GNUNET_DISK_OpenFlags flags, } #endif - ret = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); + ret = GNUNET_new (struct GNUNET_DISK_FileHandle); #ifdef MINGW ret->h = h; ret->type = GNUNET_DISK_HANLDE_TYPE_FILE; @@ -1816,9 +1769,10 @@ GNUNET_DISK_file_open (const char *fn, enum GNUNET_DISK_OpenFlags flags, /** - * Close an open file + * Close an open file. + * * @param h file handle - * @return GNUNET_OK on success, GNUNET_SYSERR otherwise + * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_DISK_file_close (struct GNUNET_DISK_FileHandle *h) @@ -1833,7 +1787,7 @@ GNUNET_DISK_file_close (struct GNUNET_DISK_FileHandle *h) ret = GNUNET_OK; #if MINGW - if (!CloseHandle (h->h)) + if (! CloseHandle (h->h)) { SetErrnoFromWinError (GetLastError ()); LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "close"); @@ -1841,7 +1795,7 @@ GNUNET_DISK_file_close (struct GNUNET_DISK_FileHandle *h) } if (h->oOverlapRead) { - if (!CloseHandle (h->oOverlapRead->hEvent)) + if (! CloseHandle (h->oOverlapRead->hEvent)) { SetErrnoFromWinError (GetLastError ()); LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "close"); @@ -1870,6 +1824,7 @@ GNUNET_DISK_file_close (struct GNUNET_DISK_FileHandle *h) return ret; } + #ifdef WINDOWS /** * Get a GNUnet file handle from a W32 handle. @@ -1881,7 +1836,6 @@ struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_w32_handle (HANDLE osfh) { struct GNUNET_DISK_FileHandle *fh; - DWORD dwret; enum GNUNET_FILE_Type ftype; @@ -1894,11 +1848,23 @@ GNUNET_DISK_get_handle_from_w32_handle (HANDLE osfh) case FILE_TYPE_PIPE: ftype = GNUNET_DISK_HANLDE_TYPE_PIPE; break; + case FILE_TYPE_UNKNOWN: + if ( (GetLastError () == NO_ERROR) || + (GetLastError () == ERROR_INVALID_HANDLE) ) + { + if (0 != ResetEvent (osfh)) + ftype = GNUNET_DISK_HANLDE_TYPE_EVENT; + else + return NULL; + } + else + return NULL; + break; default: return NULL; } - fh = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); + fh = GNUNET_new (struct GNUNET_DISK_FileHandle); fh->h = osfh; fh->type = ftype; @@ -1912,8 +1878,8 @@ GNUNET_DISK_get_handle_from_w32_handle (HANDLE osfh) * otherwise we're screwed, as selecting on non-overlapped handle * will block. */ - fh->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); - fh->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); + fh->oOverlapRead = GNUNET_new (OVERLAPPED); + fh->oOverlapWrite = GNUNET_new (OVERLAPPED); fh->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); fh->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); } @@ -1926,15 +1892,19 @@ GNUNET_DISK_get_handle_from_w32_handle (HANDLE osfh) * Get a handle from a native integer FD. * * @param fno native integer file descriptor - * @return file handle corresponding to the descriptor + * @return file handle corresponding to the descriptor, NULL on error */ struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd (int fno) { struct GNUNET_DISK_FileHandle *fh; + if ( (((off_t) -1) == lseek (fno, 0, SEEK_CUR)) && + (EBADF == errno) ) + return NULL; /* invalid FD */ + #ifndef WINDOWS - fh = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); + fh = GNUNET_new (struct GNUNET_DISK_FileHandle); fh->fd = fno; #else @@ -1970,78 +1940,6 @@ GNUNET_DISK_get_handle_from_native (FILE *fd) } -/** - * Construct full path to a file inside of the private - * directory used by GNUnet. Also creates the corresponding - * directory. If the resulting name is supposed to be - * a directory, end the last argument in '/' (or pass - * DIR_SEPARATOR_STR as the last argument before NULL). - * - * @param cfg configuration to use (determines HOME) - * @param serviceName name of the service - * @param ... is NULL-terminated list of - * path components to append to the - * private directory name. - * @return the constructed filename - */ -char * -GNUNET_DISK_get_home_filename (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *serviceName, ...) -{ - const char *c; - char *pfx; - char *ret; - va_list ap; - unsigned int needed; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, serviceName, "HOME", &pfx)) - return NULL; - if (pfx == NULL) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - _("No `%s' specified for service `%s' in configuration.\n"), "HOME", - serviceName); - return NULL; - } - needed = strlen (pfx) + 2; - if ((pfx[strlen (pfx) - 1] != '/') && (pfx[strlen (pfx) - 1] != '\\')) - needed++; - va_start (ap, serviceName); - while (1) - { - c = va_arg (ap, const char *); - - if (c == NULL) - break; - needed += strlen (c); - if ((c[strlen (c) - 1] != '/') && (c[strlen (c) - 1] != '\\')) - needed++; - } - va_end (ap); - ret = GNUNET_malloc (needed); - strcpy (ret, pfx); - GNUNET_free (pfx); - va_start (ap, serviceName); - while (1) - { - c = va_arg (ap, const char *); - - if (c == NULL) - break; - if ((c[strlen (c) - 1] != '/') && (c[strlen (c) - 1] != '\\')) - strcat (ret, DIR_SEPARATOR_STR); - strcat (ret, c); - } - va_end (ap); - if ((ret[strlen (ret) - 1] != '/') && (ret[strlen (ret) - 1] != '\\')) - (void) GNUNET_DISK_directory_create_for_file (ret); - else - (void) GNUNET_DISK_directory_create (ret); - return ret; -} - - /** * Handle for a memory-mapping operation. */ @@ -2115,7 +2013,7 @@ GNUNET_DISK_file_map (const struct GNUNET_DISK_FileHandle *h, return NULL; } - *m = GNUNET_malloc (sizeof (struct GNUNET_DISK_MapHandle)); + *m = GNUNET_new (struct GNUNET_DISK_MapHandle); (*m)->h = CreateFileMapping (h->h, NULL, protect, 0, 0, NULL); if ((*m)->h == INVALID_HANDLE_VALUE) { @@ -2141,7 +2039,7 @@ GNUNET_DISK_file_map (const struct GNUNET_DISK_FileHandle *h, prot = PROT_READ; if (access & GNUNET_DISK_MAP_TYPE_WRITE) prot |= PROT_WRITE; - *m = GNUNET_malloc (sizeof (struct GNUNET_DISK_MapHandle)); + *m = GNUNET_new (struct GNUNET_DISK_MapHandle); (*m)->addr = mmap (NULL, len, prot, MAP_SHARED, h->fd, 0); GNUNET_assert (NULL != (*m)->addr); if (MAP_FAILED == (*m)->addr) @@ -2217,6 +2115,9 @@ GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h) #if WINDOWS +#ifndef PIPE_BUF +#define PIPE_BUF 512 +#endif /* Copyright Bob Byrnes curl.com> http://permalink.gmane.org/gmane.os.cygwin.patches/2121 */ @@ -2346,18 +2247,24 @@ create_selectable_pipe (PHANDLE read_pipe_ptr, PHANDLE write_pipe_ptr, * @return handle to the new pipe, NULL on error */ struct GNUNET_DISK_PipeHandle * -GNUNET_DISK_pipe (int blocking_read, int blocking_write, int inherit_read, int inherit_write) +GNUNET_DISK_pipe (int blocking_read, + int blocking_write, + int inherit_read, + int inherit_write) { #ifndef MINGW int fd[2]; int ret; int eno; + (void) inherit_read; + (void) inherit_write; ret = pipe (fd); if (ret == -1) { eno = errno; - LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "pipe"); + LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, + "pipe"); errno = eno; return NULL; } @@ -2370,9 +2277,9 @@ GNUNET_DISK_pipe (int blocking_read, int blocking_write, int inherit_read, int i HANDLE tmp_handle; int save_errno; - p = GNUNET_malloc (sizeof (struct GNUNET_DISK_PipeHandle)); - p->fd[0] = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); - p->fd[1] = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); + p = GNUNET_new (struct GNUNET_DISK_PipeHandle); + p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle); + p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle); /* All pipes are overlapped. If you want them to block - just * call WriteFile() and ReadFile() with NULL overlapped pointer. @@ -2434,10 +2341,10 @@ GNUNET_DISK_pipe (int blocking_read, int blocking_write, int inherit_read, int i p->fd[0]->type = GNUNET_DISK_HANLDE_TYPE_PIPE; p->fd[1]->type = GNUNET_DISK_HANLDE_TYPE_PIPE; - p->fd[0]->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); - p->fd[0]->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); - p->fd[1]->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); - p->fd[1]->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); + p->fd[0]->oOverlapRead = GNUNET_new (OVERLAPPED); + p->fd[0]->oOverlapWrite = GNUNET_new (OVERLAPPED); + p->fd[1]->oOverlapRead = GNUNET_new (OVERLAPPED); + p->fd[1]->oOverlapWrite = GNUNET_new (OVERLAPPED); p->fd[0]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); p->fd[0]->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); @@ -2465,7 +2372,7 @@ GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2]) { struct GNUNET_DISK_PipeHandle *p; - p = GNUNET_malloc (sizeof (struct GNUNET_DISK_PipeHandle)); + p = GNUNET_new (struct GNUNET_DISK_PipeHandle); #ifndef MINGW int ret; @@ -2475,7 +2382,7 @@ GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2]) ret = 0; if (fd[0] >= 0) { - p->fd[0] = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); + p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle); p->fd[0]->fd = fd[0]; if (!blocking_read) { @@ -2498,7 +2405,7 @@ GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2]) if (fd[1] >= 0) { - p->fd[1] = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); + p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle); p->fd[1]->fd = fd[1]; if (!blocking_write) { @@ -2535,13 +2442,13 @@ GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2]) #else if (fd[0] >= 0) { - p->fd[0] = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); + p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle); p->fd[0]->h = (HANDLE) _get_osfhandle (fd[0]); if (p->fd[0]->h != INVALID_HANDLE_VALUE) { p->fd[0]->type = GNUNET_DISK_HANLDE_TYPE_PIPE; - p->fd[0]->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); - p->fd[0]->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); + p->fd[0]->oOverlapRead = GNUNET_new (OVERLAPPED); + p->fd[0]->oOverlapWrite = GNUNET_new (OVERLAPPED); p->fd[0]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); p->fd[0]->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); } @@ -2553,13 +2460,13 @@ GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2]) } if (fd[1] >= 0) { - p->fd[1] = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); + p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle); p->fd[1]->h = (HANDLE) _get_osfhandle (fd[1]); if (p->fd[1]->h != INVALID_HANDLE_VALUE) { p->fd[1]->type = GNUNET_DISK_HANLDE_TYPE_PIPE; - p->fd[1]->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); - p->fd[1]->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); + p->fd[1]->oOverlapRead = GNUNET_new (OVERLAPPED); + p->fd[1]->oOverlapWrite = GNUNET_new (OVERLAPPED); p->fd[1]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); p->fd[1]->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); } @@ -2713,12 +2620,14 @@ GNUNET_DISK_pipe_handle (const struct GNUNET_DISK_PipeHandle *p, * @param fh GNUnet file descriptor * @param dst destination buffer * @param dst_len length of dst - * @return GNUNET_OK on success, GNUNET_SYSERR otherwise + * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_DISK_internal_file_handle_ (const struct GNUNET_DISK_FileHandle *fh, void *dst, size_t dst_len) { + if (NULL == fh) + return GNUNET_SYSERR; #ifdef MINGW if (dst_len < sizeof (HANDLE)) return GNUNET_SYSERR;