diff options
author | Nils Durner <durner@gnunet.org> | 2009-06-15 20:11:51 +0000 |
---|---|---|
committer | Nils Durner <durner@gnunet.org> | 2009-06-15 20:11:51 +0000 |
commit | 1088905b5a89a24706d2c1877d289589e3f3c222 (patch) | |
tree | 38ec7cdc1b80502aa950c68ebefe1e3f42efa14b /src/util/disk.c | |
parent | 7e3df72d6b8a32b15b02110b54c77f77e28928a2 (diff) | |
download | gnunet-1088905b5a89a24706d2c1877d289589e3f3c222.tar.gz gnunet-1088905b5a89a24706d2c1877d289589e3f3c222.zip |
more complete DISK API
Diffstat (limited to 'src/util/disk.c')
-rw-r--r-- | src/util/disk.c | 566 |
1 files changed, 452 insertions, 114 deletions
diff --git a/src/util/disk.c b/src/util/disk.c index 5042f0867..b0d3b18a4 100644 --- a/src/util/disk.c +++ b/src/util/disk.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2001, 2002, 2005, 2006 Christian Grothoff (and other contributing authors) | 3 | (C) 2001, 2002, 2005, 2006, 2009 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -22,11 +22,14 @@ | |||
22 | * @file util/disk.c | 22 | * @file util/disk.c |
23 | * @brief disk IO convenience methods | 23 | * @brief disk IO convenience methods |
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | * @author Nils Durner | ||
25 | */ | 26 | */ |
26 | 27 | ||
27 | #include "platform.h" | 28 | #include "platform.h" |
29 | #include "io_handle.h" | ||
28 | #include "gnunet_common.h" | 30 | #include "gnunet_common.h" |
29 | #include "gnunet_directories.h" | 31 | #include "gnunet_directories.h" |
32 | #include "gnunet_io_lib.h" | ||
30 | #include "gnunet_disk_lib.h" | 33 | #include "gnunet_disk_lib.h" |
31 | #include "gnunet_scheduler_lib.h" | 34 | #include "gnunet_scheduler_lib.h" |
32 | #include "gnunet_strings_lib.h" | 35 | #include "gnunet_strings_lib.h" |
@@ -108,6 +111,44 @@ getSizeRec (void *ptr, const char *fn) | |||
108 | return GNUNET_OK; | 111 | return GNUNET_OK; |
109 | } | 112 | } |
110 | 113 | ||
114 | |||
115 | /** | ||
116 | * Move the read/write pointer in a file | ||
117 | * @param h handle of an open file | ||
118 | * @param offset position to move to | ||
119 | * @param whence specification to which position the offset parameter relates to | ||
120 | * @return the new position on success, GNUNET_SYSERR otherwise | ||
121 | */ | ||
122 | off_t | ||
123 | GNUNET_DISK_file_seek (const struct GNUNET_IO_Handle *h, off_t offset, | ||
124 | enum GNUNET_DISK_Seek whence) | ||
125 | { | ||
126 | if (h == NULL) | ||
127 | { | ||
128 | errno = EINVAL; | ||
129 | return GNUNET_SYSERR; | ||
130 | } | ||
131 | |||
132 | #ifdef MINGW | ||
133 | DWORD ret; | ||
134 | static DWORD t[] = { [GNUNET_SEEK_SET] = FILE_BEGIN, | ||
135 | [GNUNET_SEEK_CUR] = FILE_CURRENT, [GNUNET_SEEK_END] = FILE_END }; | ||
136 | |||
137 | ret = SetFilePointer (h->h, offset, NULL, t[whence]); | ||
138 | if (ret == INVALID_SET_FILE_POINTER) | ||
139 | { | ||
140 | SetErrnoFromWinError (GetLastError ()); | ||
141 | return GNUNET_SYSERR; | ||
142 | } | ||
143 | return ret; | ||
144 | #else | ||
145 | static int t[] = { [GNUNET_SEEK_SET] = SEEK_SET, | ||
146 | [GNUNET_SEEK_CUR] = SEEK_CUR, [GNUNET_SEEK_END] = SEEK_END }; | ||
147 | |||
148 | return lseek (h->fd, offset, t[whence]); | ||
149 | #endif | ||
150 | } | ||
151 | |||
111 | /** | 152 | /** |
112 | * Get the size of the file (or directory) | 153 | * Get the size of the file (or directory) |
113 | * of the given file (in bytes). | 154 | * of the given file (in bytes). |
@@ -129,6 +170,7 @@ GNUNET_DISK_file_size (const char *filename, | |||
129 | return ret; | 170 | return ret; |
130 | } | 171 | } |
131 | 172 | ||
173 | |||
132 | /** | 174 | /** |
133 | * Get the number of blocks that are left on the partition that | 175 | * Get the number of blocks that are left on the partition that |
134 | * contains the given file (for normal users). | 176 | * contains the given file (for normal users). |
@@ -359,30 +401,55 @@ GNUNET_DISK_directory_create_for_file (const char *dir) | |||
359 | 401 | ||
360 | /** | 402 | /** |
361 | * Read the contents of a binary file into a buffer. | 403 | * Read the contents of a binary file into a buffer. |
362 | * @param fileName the name of the file, not freed, | 404 | * @param h handle to an open file |
363 | * must already be expanded! | 405 | * @param result the buffer to write the result to |
364 | * @param len the maximum number of bytes to read | 406 | * @param len the maximum number of bytes to read |
407 | * @return the number of bytes read on success, GNUNET_SYSERR on failure | ||
408 | */ | ||
409 | int | ||
410 | GNUNET_DISK_file_read (const struct GNUNET_IO_Handle *h, void *result, int len) | ||
411 | { | ||
412 | if (h == NULL) | ||
413 | { | ||
414 | errno = EINVAL; | ||
415 | return GNUNET_SYSERR; | ||
416 | } | ||
417 | |||
418 | #ifdef MINGW | ||
419 | DWORD bytesRead; | ||
420 | |||
421 | if (!ReadFile (h->h, result, len, &bytesRead, NULL)) | ||
422 | { | ||
423 | SetErrnoFromWinError (GetLastError ()); | ||
424 | return GNUNET_SYSERR; | ||
425 | } | ||
426 | return bytesRead; | ||
427 | #else | ||
428 | return read (h->fd, result, len); | ||
429 | #endif | ||
430 | } | ||
431 | |||
432 | |||
433 | /** | ||
434 | * Read the contents of a binary file into a buffer. | ||
435 | * @param fn file name | ||
365 | * @param result the buffer to write the result to | 436 | * @param result the buffer to write the result to |
366 | * @return the number of bytes read on success, -1 on failure | 437 | * @param len the maximum number of bytes to read |
438 | * @return the number of bytes read on success, GNUNET_SYSERR on failure | ||
367 | */ | 439 | */ |
368 | int | 440 | int |
369 | GNUNET_DISK_file_read (const char *fileName, int len, void *result) | 441 | GNUNET_DISK_fn_read (const char * const fn, void *result, int len) |
370 | { | 442 | { |
371 | /* open file, must exist, open read only */ | 443 | struct GNUNET_IO_Handle *fh; |
372 | int handle; | 444 | int ret; |
373 | int size; | 445 | |
374 | 446 | fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READ); | |
375 | GNUNET_assert (fileName != NULL); | 447 | if (!fh) |
376 | GNUNET_assert (len > 0); | 448 | return GNUNET_SYSERR; |
377 | if (len == 0) | 449 | ret = GNUNET_DISK_file_read (fh, result, len); |
378 | return 0; | 450 | GNUNET_assert(GNUNET_OK == GNUNET_DISK_file_close(&fh)); |
379 | GNUNET_assert (result != NULL); | 451 | |
380 | handle = GNUNET_DISK_file_open (fileName, O_RDONLY, S_IRUSR); | 452 | return ret; |
381 | if (handle < 0) | ||
382 | return -1; | ||
383 | size = READ (handle, result, len); | ||
384 | GNUNET_DISK_file_close (fileName, handle); | ||
385 | return size; | ||
386 | } | 453 | } |
387 | 454 | ||
388 | 455 | ||
@@ -404,45 +471,57 @@ atoo (const char *s) | |||
404 | 471 | ||
405 | /** | 472 | /** |
406 | * Write a buffer to a file. | 473 | * Write a buffer to a file. |
407 | * @param fileName the name of the file, NOT freed! | 474 | * @param h handle to open file |
408 | * @param buffer the data to write | 475 | * @param buffer the data to write |
409 | * @param n number of bytes to write | 476 | * @param n number of bytes to write |
410 | * @param mode permissions to set on the file | 477 | * @return number of bytes written on success, GNUNET_SYSERR on error |
411 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
412 | */ | 478 | */ |
413 | int | 479 | int |
414 | GNUNET_DISK_file_write (const char *fileName, | 480 | GNUNET_DISK_file_write (const struct GNUNET_IO_Handle *h, const void *buffer, |
415 | const void *buffer, unsigned int n, const char *mode) | 481 | unsigned int n) |
416 | { | 482 | { |
417 | int handle; | 483 | if (h == NULL) |
418 | char *fn; | ||
419 | |||
420 | /* open file, open with 600, create if not | ||
421 | present, otherwise overwrite */ | ||
422 | GNUNET_assert (fileName != NULL); | ||
423 | fn = GNUNET_STRINGS_filename_expand (fileName); | ||
424 | handle = GNUNET_DISK_file_open (fn, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); | ||
425 | if (handle == -1) | ||
426 | { | 484 | { |
427 | GNUNET_free (fn); | 485 | errno = EINVAL; |
428 | return GNUNET_SYSERR; | 486 | return GNUNET_SYSERR; |
429 | } | 487 | } |
430 | GNUNET_assert ((n == 0) || (buffer != NULL)); | 488 | |
431 | /* write the buffer take length from the beginning */ | 489 | #ifdef MINGW |
432 | if (n != WRITE (handle, buffer, n)) | 490 | DWORD bytesWritten; |
491 | |||
492 | if (!WriteFile (h->h, buffer, n, &bytesWritten, NULL)) | ||
433 | { | 493 | { |
434 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", fn); | 494 | SetErrnoFromWinError (GetLastError ()); |
435 | GNUNET_DISK_file_close (fn, handle); | ||
436 | GNUNET_free (fn); | ||
437 | return GNUNET_SYSERR; | 495 | return GNUNET_SYSERR; |
438 | } | 496 | } |
439 | GNUNET_DISK_file_close (fn, handle); | 497 | return bytesWritten; |
440 | if (0 != CHMOD (fn, atoo (mode))) | 498 | #else |
441 | { | 499 | return write (h->fd, buffer, n); |
442 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "chmod", fn); | 500 | #endif |
443 | } | 501 | } |
444 | GNUNET_free (fn); | 502 | |
445 | return GNUNET_OK; | 503 | /** |
504 | * Write a buffer to a file. | ||
505 | * @param fn file name | ||
506 | * @param buffer the data to write | ||
507 | * @param n number of bytes to write | ||
508 | * @return number of bytes written on success, GNUNET_SYSERR on error | ||
509 | */ | ||
510 | int | ||
511 | GNUNET_DISK_fn_write (const char * const fn, const void *buffer, | ||
512 | unsigned int n, int mode) | ||
513 | { | ||
514 | struct GNUNET_IO_Handle *fh; | ||
515 | int ret; | ||
516 | |||
517 | fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_WRITE | ||
518 | | GNUNET_DISK_OPEN_CREATE, mode); | ||
519 | if (!fh) | ||
520 | return GNUNET_SYSERR; | ||
521 | ret = GNUNET_DISK_file_write (fh, buffer, n); | ||
522 | GNUNET_assert(GNUNET_OK == GNUNET_DISK_file_close(&fh)); | ||
523 | |||
524 | return ret; | ||
446 | } | 525 | } |
447 | 526 | ||
448 | /** | 527 | /** |
@@ -724,57 +803,6 @@ GNUNET_DISK_directory_remove (const char *fileName) | |||
724 | return GNUNET_OK; | 803 | return GNUNET_OK; |
725 | } | 804 | } |
726 | 805 | ||
727 | void | ||
728 | GNUNET_DISK_file_close (const char *filename, int fd) | ||
729 | { | ||
730 | if (0 != CLOSE (fd)) | ||
731 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "close", filename); | ||
732 | } | ||
733 | |||
734 | int | ||
735 | GNUNET_DISK_file_open (const char *filename, int oflag, ...) | ||
736 | { | ||
737 | char *fn; | ||
738 | int mode; | ||
739 | int ret; | ||
740 | #ifdef MINGW | ||
741 | char szFile[_MAX_PATH + 1]; | ||
742 | long lRet; | ||
743 | |||
744 | if ((lRet = plibc_conv_to_win_path (filename, szFile)) != ERROR_SUCCESS) | ||
745 | { | ||
746 | errno = ENOENT; | ||
747 | SetLastError (lRet); | ||
748 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
749 | "plibc_conv_to_win_path", filename); | ||
750 | return -1; | ||
751 | } | ||
752 | fn = GNUNET_strdup (szFile); | ||
753 | #else | ||
754 | fn = GNUNET_STRINGS_filename_expand (filename); | ||
755 | #endif | ||
756 | if (oflag & O_CREAT) | ||
757 | { | ||
758 | va_list arg; | ||
759 | va_start (arg, oflag); | ||
760 | mode = va_arg (arg, int); | ||
761 | va_end (arg); | ||
762 | } | ||
763 | else | ||
764 | { | ||
765 | mode = 0; | ||
766 | } | ||
767 | #ifdef MINGW | ||
768 | /* set binary mode */ | ||
769 | oflag |= O_BINARY; | ||
770 | #endif | ||
771 | ret = OPEN (fn, oflag, mode); | ||
772 | if (ret == -1) | ||
773 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "open", fn); | ||
774 | GNUNET_free (fn); | ||
775 | return ret; | ||
776 | } | ||
777 | |||
778 | #define COPY_BLK_SIZE 65536 | 806 | #define COPY_BLK_SIZE 65536 |
779 | 807 | ||
780 | /** | 808 | /** |
@@ -788,21 +816,21 @@ GNUNET_DISK_file_copy (const char *src, const char *dst) | |||
788 | unsigned long long pos; | 816 | unsigned long long pos; |
789 | unsigned long long size; | 817 | unsigned long long size; |
790 | unsigned long long len; | 818 | unsigned long long len; |
791 | int in; | 819 | struct GNUNET_IO_Handle *in, *out; |
792 | int out; | ||
793 | 820 | ||
794 | if (GNUNET_OK != GNUNET_DISK_file_size (src, &size, GNUNET_YES)) | 821 | if (GNUNET_OK != GNUNET_DISK_file_size (src, &size, GNUNET_YES)) |
795 | return GNUNET_SYSERR; | 822 | return GNUNET_SYSERR; |
796 | pos = 0; | 823 | pos = 0; |
797 | in = GNUNET_DISK_file_open (src, O_RDONLY | O_LARGEFILE); | 824 | in = GNUNET_DISK_file_open (src, GNUNET_DISK_OPEN_READ); |
798 | if (in == -1) | 825 | if (!in) |
799 | return GNUNET_SYSERR; | 826 | return GNUNET_SYSERR; |
800 | out = GNUNET_DISK_file_open (dst, | 827 | out = GNUNET_DISK_file_open (dst, GNUNET_DISK_OPEN_WRITE |
801 | O_LARGEFILE | O_WRONLY | O_CREAT | O_EXCL, | 828 | | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS, |
802 | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); | 829 | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE |
803 | if (out == -1) | 830 | | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_GROUP_WRITE); |
831 | if (!out) | ||
804 | { | 832 | { |
805 | GNUNET_DISK_file_close (src, in); | 833 | GNUNET_DISK_file_close (&in); |
806 | return GNUNET_SYSERR; | 834 | return GNUNET_SYSERR; |
807 | } | 835 | } |
808 | buf = GNUNET_malloc (COPY_BLK_SIZE); | 836 | buf = GNUNET_malloc (COPY_BLK_SIZE); |
@@ -811,20 +839,20 @@ GNUNET_DISK_file_copy (const char *src, const char *dst) | |||
811 | len = COPY_BLK_SIZE; | 839 | len = COPY_BLK_SIZE; |
812 | if (len > size - pos) | 840 | if (len > size - pos) |
813 | len = size - pos; | 841 | len = size - pos; |
814 | if (len != READ (in, buf, len)) | 842 | if (len != GNUNET_DISK_file_read (in, buf, len)) |
815 | goto FAIL; | 843 | goto FAIL; |
816 | if (len != WRITE (out, buf, len)) | 844 | if (len != GNUNET_DISK_file_write (out, buf, len)) |
817 | goto FAIL; | 845 | goto FAIL; |
818 | pos += len; | 846 | pos += len; |
819 | } | 847 | } |
820 | GNUNET_free (buf); | 848 | GNUNET_free (buf); |
821 | GNUNET_DISK_file_close (src, in); | 849 | GNUNET_DISK_file_close (&in); |
822 | GNUNET_DISK_file_close (dst, out); | 850 | GNUNET_DISK_file_close (&out); |
823 | return GNUNET_OK; | 851 | return GNUNET_OK; |
824 | FAIL: | 852 | FAIL: |
825 | GNUNET_free (buf); | 853 | GNUNET_free (buf); |
826 | GNUNET_DISK_file_close (src, in); | 854 | GNUNET_DISK_file_close (&in); |
827 | GNUNET_DISK_file_close (dst, out); | 855 | GNUNET_DISK_file_close (&out); |
828 | return GNUNET_SYSERR; | 856 | return GNUNET_SYSERR; |
829 | } | 857 | } |
830 | 858 | ||
@@ -881,6 +909,177 @@ GNUNET_DISK_file_change_owner (const char *filename, const char *user) | |||
881 | 909 | ||
882 | 910 | ||
883 | /** | 911 | /** |
912 | * Lock a part of a file | ||
913 | * @param fh file handle | ||
914 | * @lockStart absolute position from where to lock | ||
915 | * @lockEnd absolute position until where to lock | ||
916 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
917 | */ | ||
918 | int | ||
919 | GNUNET_DISK_file_lock(struct GNUNET_IO_Handle *fh, off_t lockStart, | ||
920 | off_t lockEnd) | ||
921 | { | ||
922 | if (fh == NULL) | ||
923 | { | ||
924 | errno = EINVAL; | ||
925 | return GNUNET_SYSERR; | ||
926 | } | ||
927 | |||
928 | #ifndef MINGW | ||
929 | struct flock fl; | ||
930 | |||
931 | memset(&fl, 0, sizeof(struct flock)); | ||
932 | fl.l_type = F_WRLCK; | ||
933 | fl.l_whence = SEEK_SET; | ||
934 | fl.l_start = lockStart; | ||
935 | fl.l_len = lockEnd; | ||
936 | |||
937 | return fcntl(fh->fd, F_SETLK, &fl) != 0 ? GNUNET_SYSERR : GNUNET_OK; | ||
938 | #else | ||
939 | if (!LockFile(fh->h, 0, lockStart, 0, lockEnd)) | ||
940 | { | ||
941 | SetErrnoFromWinError(GetLastError()); | ||
942 | return GNUNET_SYSERR; | ||
943 | } | ||
944 | |||
945 | return GNUNET_OK; | ||
946 | #endif | ||
947 | } | ||
948 | |||
949 | |||
950 | /** | ||
951 | * Open a file | ||
952 | * @param fn file name to be opened | ||
953 | * @param flags opening flags, a combination of GNUNET_DISK_OPEN_xxx bit flags | ||
954 | * @param perm permissions for the newly created file | ||
955 | * @return IO handle on success, NULL on error | ||
956 | */ | ||
957 | struct GNUNET_IO_Handle * | ||
958 | GNUNET_DISK_file_open (const char *fn, int flags, ...) | ||
959 | { | ||
960 | char *expfn; | ||
961 | struct GNUNET_IO_Handle *ret; | ||
962 | #ifdef MINGW | ||
963 | DWORD access, disp; | ||
964 | HANDLE h; | ||
965 | #else | ||
966 | int oflags, mode; | ||
967 | int fd; | ||
968 | #endif | ||
969 | |||
970 | expfn = GNUNET_STRINGS_filename_expand (fn); | ||
971 | |||
972 | #ifndef MINGW | ||
973 | oflags = 0; | ||
974 | if (flags & GNUNET_DISK_OPEN_READ) | ||
975 | oflags = O_RDONLY; | ||
976 | if (flags & GNUNET_DISK_OPEN_WRITE) | ||
977 | oflags |= O_WRONLY; | ||
978 | if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS) | ||
979 | oflags |= (O_CREAT & O_EXCL); | ||
980 | if (flags & GNUNET_DISK_OPEN_TRUNCATE) | ||
981 | oflags |= O_TRUNC; | ||
982 | if (flags & GNUNET_DISK_OPEN_CREATE) | ||
983 | { | ||
984 | oflags |= O_CREAT; | ||
985 | |||
986 | va_list arg; | ||
987 | va_start (arg, oflag); | ||
988 | mode = va_arg (arg, int); | ||
989 | va_end (arg); | ||
990 | } | ||
991 | if (flags & GNUNET_DISK_OPEN_APPEND) | ||
992 | oflags = O_APPEND; | ||
993 | |||
994 | fd = open (expfn, oflag | O_LARGEFILE, perm, mode); | ||
995 | if (fd == -1) | ||
996 | { | ||
997 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "open", fn); | ||
998 | return NULL; | ||
999 | } | ||
1000 | #else | ||
1001 | access = 0; | ||
1002 | disp = OPEN_ALWAYS; | ||
1003 | |||
1004 | if (flags & GNUNET_DISK_OPEN_READ) | ||
1005 | access = FILE_READ_DATA; | ||
1006 | if (flags & GNUNET_DISK_OPEN_WRITE) | ||
1007 | access = FILE_WRITE_DATA; | ||
1008 | |||
1009 | if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS) | ||
1010 | disp = CREATE_NEW; | ||
1011 | if (flags & GNUNET_DISK_OPEN_TRUNCATE) | ||
1012 | disp = TRUNCATE_EXISTING; | ||
1013 | if (flags & GNUNET_DISK_OPEN_CREATE) | ||
1014 | disp |= OPEN_ALWAYS; | ||
1015 | |||
1016 | /* TODO: access priviledges? */ | ||
1017 | h = CreateFile (expfn, access, FILE_SHARE_DELETE | FILE_SHARE_READ | ||
1018 | | FILE_SHARE_WRITE, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL); | ||
1019 | if (h == INVALID_HANDLE_VALUE) | ||
1020 | { | ||
1021 | SetErrnoFromWinError (GetLastError ()); | ||
1022 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "open", fn); | ||
1023 | return NULL; | ||
1024 | } | ||
1025 | |||
1026 | if (flags & GNUNET_DISK_OPEN_APPEND) | ||
1027 | if (SetFilePointer (h, 0, 0, FILE_END) == INVALID_SET_FILE_POINTER) | ||
1028 | { | ||
1029 | SetErrnoFromWinError (GetLastError ()); | ||
1030 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "SetFilePointer", fn); | ||
1031 | CloseHandle (h); | ||
1032 | return NULL; | ||
1033 | } | ||
1034 | #endif | ||
1035 | |||
1036 | ret = (struct GNUNET_IO_Handle *) GNUNET_malloc(sizeof(struct GNUNET_IO_Handle)); | ||
1037 | #ifdef MINGW | ||
1038 | ret->h = h; | ||
1039 | #else | ||
1040 | ret->fd = fd; | ||
1041 | #endif | ||
1042 | |||
1043 | return ret; | ||
1044 | } | ||
1045 | |||
1046 | /** | ||
1047 | * Close an open file | ||
1048 | * @param h file handle | ||
1049 | * @return GNUNET_OK on success, GNUNET_SYSERR otherwise | ||
1050 | */ | ||
1051 | int | ||
1052 | GNUNET_DISK_file_close (struct GNUNET_IO_Handle **h) | ||
1053 | { | ||
1054 | if (*h == NULL) | ||
1055 | { | ||
1056 | errno = EINVAL; | ||
1057 | return GNUNET_SYSERR; | ||
1058 | } | ||
1059 | |||
1060 | #if MINGW | ||
1061 | if (!CloseHandle ((*h)->h)) | ||
1062 | { | ||
1063 | SetErrnoFromWinError (GetLastError ()); | ||
1064 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "close"); | ||
1065 | return GNUNET_SYSERR; | ||
1066 | } | ||
1067 | #else | ||
1068 | if (close ((*h)->fd) != 0) | ||
1069 | { | ||
1070 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "close"); | ||
1071 | return GNUNET_SYSERR; | ||
1072 | } | ||
1073 | #endif | ||
1074 | |||
1075 | GNUNET_IO_handle_invalidate (*h); | ||
1076 | free(*h); | ||
1077 | *h = NULL; | ||
1078 | |||
1079 | return GNUNET_OK; | ||
1080 | } | ||
1081 | |||
1082 | /** | ||
884 | * Construct full path to a file inside of the private | 1083 | * Construct full path to a file inside of the private |
885 | * directory used by GNUnet. Also creates the corresponding | 1084 | * directory used by GNUnet. Also creates the corresponding |
886 | * directory. If the resulting name is supposed to be | 1085 | * directory. If the resulting name is supposed to be |
@@ -949,6 +1148,145 @@ GNUNET_DISK_get_home_filename (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
949 | return ret; | 1148 | return ret; |
950 | } | 1149 | } |
951 | 1150 | ||
1151 | /** | ||
1152 | * Map a file into memory | ||
1153 | * @param h open file handle | ||
1154 | * @param m handle to the new mapping | ||
1155 | * @param access access specification, GNUNET_DISK_MAP_xxx | ||
1156 | * @param len size of the mapping | ||
1157 | * @return pointer to the mapped memory region, NULL on failure | ||
1158 | */ | ||
1159 | void * | ||
1160 | GNUNET_DISK_file_map (const struct GNUNET_IO_Handle *h, struct GNUNET_IO_Handle **m, | ||
1161 | int access, size_t len) | ||
1162 | { | ||
1163 | if (h == NULL) | ||
1164 | { | ||
1165 | errno = EINVAL; | ||
1166 | return NULL; | ||
1167 | } | ||
1168 | |||
1169 | #ifdef MINGW | ||
1170 | DWORD mapAccess, protect; | ||
1171 | void *ret; | ||
1172 | |||
1173 | if (access & GNUNET_DISK_MAP_READ && access & GNUNET_DISK_MAP_WRITE) | ||
1174 | { | ||
1175 | protect = PAGE_READWRITE; | ||
1176 | mapAccess = FILE_MAP_ALL_ACCESS; | ||
1177 | } | ||
1178 | else if (access & GNUNET_DISK_MAP_READ) | ||
1179 | { | ||
1180 | protect = PAGE_READONLY; | ||
1181 | mapAccess = FILE_MAP_READ; | ||
1182 | } | ||
1183 | else if (access & GNUNET_DISK_MAP_WRITE) | ||
1184 | { | ||
1185 | protect = PAGE_READWRITE; | ||
1186 | mapAccess = FILE_MAP_WRITE; | ||
1187 | } | ||
1188 | else | ||
1189 | { | ||
1190 | GNUNET_break (0); | ||
1191 | return NULL; | ||
1192 | } | ||
1193 | |||
1194 | *m = (struct GNUNET_IO_Handle *) GNUNET_malloc (sizeof (struct GNUNET_IO_Handle)); | ||
1195 | (*m)->h = CreateFileMapping (h->h, NULL, protect, 0, 0, NULL); | ||
1196 | if ((*m)->h == INVALID_HANDLE_VALUE) | ||
1197 | { | ||
1198 | SetErrnoFromWinError (GetLastError ()); | ||
1199 | GNUNET_free (*m); | ||
1200 | return NULL; | ||
1201 | } | ||
1202 | |||
1203 | ret = MapViewOfFile ((*m)->h, mapAccess, 0, 0, len); | ||
1204 | if (!ret) | ||
1205 | { | ||
1206 | SetErrnoFromWinError (GetLastError ()); | ||
1207 | CloseHandle ((*m)->h); | ||
1208 | GNUNET_free (*m); | ||
1209 | } | ||
1210 | |||
1211 | return ret; | ||
1212 | #else | ||
1213 | int prot; | ||
1214 | |||
1215 | prot = flags = 0; | ||
1216 | if (access & GNUNET_DISK_MAP_READ) | ||
1217 | prot = PROT_READ; | ||
1218 | if (access & GNUNET_DISK_MAP_WRITE) | ||
1219 | prot |= PROT_WRITE; | ||
1220 | |||
1221 | return mmap (NULL, len, prot, MAP_SHARED, h->h, 0); | ||
1222 | #endif | ||
1223 | } | ||
1224 | |||
1225 | /** | ||
1226 | * Unmap a file | ||
1227 | * @param h mapping handle | ||
1228 | * @param addr pointer to the mapped memory region | ||
1229 | * @param len size of the mapping | ||
1230 | * @return GNUNET_OK on success, GNUNET_SYSERR otherwise | ||
1231 | */ | ||
1232 | int | ||
1233 | GNUNET_DISK_file_unmap (struct GNUNET_IO_Handle **h, void *addr, size_t len) | ||
1234 | { | ||
1235 | #ifdef MINGW | ||
1236 | int ret; | ||
1237 | |||
1238 | if (h == NULL || *h == NULL) | ||
1239 | { | ||
1240 | errno = EINVAL; | ||
1241 | return GNUNET_SYSERR; | ||
1242 | } | ||
1243 | |||
1244 | ret = UnmapViewOfFile (addr) ? GNUNET_OK : GNUNET_SYSERR; | ||
1245 | if (ret != GNUNET_OK) | ||
1246 | SetErrnoFromWinError (GetLastError ()); | ||
1247 | if (!CloseHandle ((*h)->h) && ret == GNUNET_OK) | ||
1248 | { | ||
1249 | ret = GNUNET_SYSERR; | ||
1250 | SetErrnoFromWinError (GetLastError ()); | ||
1251 | } | ||
1252 | |||
1253 | GNUNET_IO_handle_invalidate (*h); | ||
1254 | GNUNET_free (*h); | ||
1255 | h = NULL; | ||
1256 | |||
1257 | return ret; | ||
1258 | #else | ||
1259 | int ret; | ||
1260 | ret = munmap (addr, len) != -1 ? GNUNET_OK : GNUNET_SYSERR; | ||
1261 | GNUNET_IO_handle_invalidate (h); | ||
1262 | return ret; | ||
1263 | #endif | ||
1264 | } | ||
1265 | |||
1266 | /** | ||
1267 | * Write file changes to disk | ||
1268 | * @param h handle to an open file | ||
1269 | * @return GNUNET_OK on success, GNUNET_SYSERR otherwise | ||
1270 | */ | ||
1271 | int | ||
1272 | GNUNET_DISK_file_sync (const struct GNUNET_IO_Handle *h) | ||
1273 | { | ||
1274 | if (h == NULL) | ||
1275 | { | ||
1276 | errno = EINVAL; | ||
1277 | return GNUNET_SYSERR; | ||
1278 | } | ||
952 | 1279 | ||
1280 | #ifdef MINGW | ||
1281 | int ret; | ||
1282 | |||
1283 | ret = FlushFileBuffers (h->h) ? GNUNET_OK : GNUNET_SYSERR; | ||
1284 | if (ret != GNUNET_OK) | ||
1285 | SetErrnoFromWinError (GetLastError ()); | ||
1286 | return ret; | ||
1287 | #else | ||
1288 | return fsync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK; | ||
1289 | #endif | ||
1290 | } | ||
953 | 1291 | ||
954 | /* end of disk.c */ | 1292 | /* end of disk.c */ |