summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2015-04-24 17:13:31 +0200
committerSimon Rettberg2015-04-24 17:13:31 +0200
commitee62ca14800eb27e51038a78a0dab4f71b6be31f (patch)
tree11bc7d301dafd884dfdfe52bf91d75dc84a83dfb
parentFuse (diff)
downloaddnbd3-ee62ca14800eb27e51038a78a0dab4f71b6be31f.tar.gz
dnbd3-ee62ca14800eb27e51038a78a0dab4f71b6be31f.tar.xz
dnbd3-ee62ca14800eb27e51038a78a0dab4f71b6be31f.zip
[FUSE] Integrate into cmake build process
-rw-r--r--CMakeLists.txt41
-rw-r--r--cmake/FindFuse.cmake30
-rw-r--r--src/fuse/helper.c96
-rw-r--r--[-rwxr-xr-x]src/fuse/helper.h (renamed from src/fuse/imageHelper.h)13
-rwxr-xr-xsrc/fuse/imageFuse.c384
-rwxr-xr-xsrc/fuse/imageHelper.c84
-rw-r--r--src/fuse/main.c348
-rw-r--r--src/fuse/serialize.c5
-rw-r--r--src/protocol.h (renamed from src/server/protocol.h)6
-rw-r--r--src/serialize.h1
-rw-r--r--src/server/altservers.c2
-rw-r--r--src/server/image.c2
-rw-r--r--src/server/uplink.c2
13 files changed, 526 insertions, 488 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0e265f7..bb00189 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,17 +24,27 @@ endif()
#SET(CMAKE_CXX_FLAGS_DEBUG "-std=c99 -O0 -g -Wall -Wno-unused-result -D_GNU_SOURCE -D_DEBUG")
#SET(CMAKE_CXX_FLAGS_RELEASE "-std=c99 -O2 -Wno-unused-result -D_GNU_SOURCE -DNDEBUG" )
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
+
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
ADD_DEFINITIONS(-DWITH_IPV6)
-FIND_PACKAGE(Threads REQUIRED)
+FIND_PACKAGE(Threads)
+FIND_PACKAGE(Fuse)
FIND_PACKAGE(PkgConfig REQUIRED)
#FIND_PACKAGE(LibXml2 REQUIRED)
-FIND_PACKAGE(ZLIB REQUIRED)
+FIND_PACKAGE(ZLIB)
+
+if(NOT FUSE_FOUND)
+ message( " *** No fuse dev libs found, won't build dnbd3-fuse" )
+endif()
+if(NOT THREADS_FOUND OR NOT ZLIB_FOUND)
+ message( " *** No threads or no zlib found, won't build dnbd3-server" )
+endif()
#PKG_CHECK_MODULES(GLIB glib-2.0 REQUIRED)
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${ZLIB_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${ZLIB_INCLUDE_DIR} ${FUSE_INCLUDE_DIR})
################################################################################
# VERSION HEADER #
@@ -71,15 +81,28 @@ ADD_DEPENDENCIES(dnbd3-client version)
# SERVER #
################################################################################
-FILE(GLOB_RECURSE SERVER_SRCS src/server/*.c)
-ADD_EXECUTABLE(dnbd3-server ${SERVER_SRCS})
-TARGET_LINK_LIBRARIES(dnbd3-server ${CMAKE_THREAD_LIBS_INIT} ${ZLIB_LIBRARIES})
-if(UNIX AND NOT APPLE)
- target_link_libraries(dnbd3-server rt)
+if(THREADS_FOUND AND ZLIB_FOUND)
+ FILE(GLOB_RECURSE SERVER_SRCS src/server/*.c)
+ ADD_EXECUTABLE(dnbd3-server ${SERVER_SRCS})
+ TARGET_LINK_LIBRARIES(dnbd3-server ${CMAKE_THREAD_LIBS_INIT} ${ZLIB_LIBRARIES})
+ if(UNIX AND NOT APPLE)
+ target_link_libraries(dnbd3-server rt)
+ endif()
+ ADD_DEPENDENCIES(dnbd3-server version)
endif()
-ADD_DEPENDENCIES(dnbd3-server version)
+################################################################################
+# FUSE #
+################################################################################
+
+if(FUSE_FOUND)
+ FILE(GLOB_RECURSE FUSE_SRCS src/fuse/*.c)
+ ADD_EXECUTABLE(dnbd3-fuse ${FUSE_SRCS})
+ TARGET_LINK_LIBRARIES(dnbd3-fuse ${FUSE_LIBRARIES})
+ ADD_DEPENDENCIES(dnbd3-fuse version)
+endif()
+
################################################################################
# MODULE #
diff --git a/cmake/FindFuse.cmake b/cmake/FindFuse.cmake
new file mode 100644
index 0000000..b9c6f91
--- /dev/null
+++ b/cmake/FindFuse.cmake
@@ -0,0 +1,30 @@
+# - Find fuse
+# Find the native fuse includes and library
+#
+# FUSE_INCLUDE_DIR - where to find fuse/fuse.h.
+# FUSE_LIBRARIES - List of libraries when using fuse.
+# FUSE_FOUND - True if fuse found.
+
+
+IF (FUSE_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(FUSE_FIND_QUIETLY TRUE)
+ENDIF (FUSE_INCLUDE_DIR)
+
+FIND_PATH(FUSE_INCLUDE_DIR fuse/fuse.h)
+
+SET(FUSE_NAMES fuse)
+FIND_LIBRARY(FUSE_LIBRARY NAMES ${FUSE_NAMES} )
+
+# handle the QUIETLY and REQUIRED arguments and set FUSE_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(FUSE REQUIRED FUSE_LIBRARY FUSE_INCLUDE_DIR)
+
+IF(FUSE_FOUND)
+ SET( FUSE_LIBRARIES ${FUSE_LIBRARY} )
+ELSE(FUSE_FOUND)
+ SET( FUSE_LIBRARIES )
+ENDIF(FUSE_FOUND)
+
+MARK_AS_ADVANCED( FUSE_LIBRARY FUSE_INCLUDE_DIR )
diff --git a/src/fuse/helper.c b/src/fuse/helper.c
new file mode 100644
index 0000000..7b1101d
--- /dev/null
+++ b/src/fuse/helper.c
@@ -0,0 +1,96 @@
+/*
+ * Helper functions for imageFuse
+ * by Stephan Schwaer, January 2014
+ */
+
+#include "helper.h"
+void printLog( log_info *info )
+{
+ FILE *logFile;
+
+ // Create logfile
+
+ logFile = fopen( "log.txt", "w" );
+ if ( logFile == NULL ) {
+ printf( "Error creating/opening log.txt\n" );
+ return;
+ }
+
+ //rewind(file);
+ fprintf( logFile, "ImageSize: %"PRIu64" MiB\n", ( uint64_t )( info->imageSize/ ( 1024ll*1024ll ) ) );
+ fprintf( logFile, "ReceivedMiB: %"PRIu64" MiB\n", ( uint64_t )( info->receivedBytes/ ( 1024ll*1024ll ) ) );
+ fprintf( logFile, "imageBlockCount: %"PRIu64"\n", info->imageBlockCount );
+ fprintf( logFile, "Blocksize: 4KiB\n\n" );
+ fprintf( logFile, "Block access count:\n" );
+
+ uint64_t i = 0;
+ for ( ; i < info->imageBlockCount; i++ ) {
+ if ( i % 50 == 0 ) {
+ fprintf( logFile, "\n" );
+ }
+ fprintf( logFile, "%i ", ( int ) info->blockRequestCount[i] );
+ }
+ fprintf( logFile, "\n" );
+ fclose( logFile );
+}
+
+bool sock_printable( struct sockaddr *addr, socklen_t addrLen, char *output, int len )
+{
+ char host[100], port[10];
+ int ret = getnameinfo( addr, addrLen, host, 100, port, 10, NI_NUMERICHOST | NI_NUMERICSERV );
+ if ( ret == 0 ) {
+ snprintf( output, len, "[%s]:%s", host, port );
+ }
+ return ret == 0;
+}
+
+// TODO: Pretty much same as in server/*
+int connect_to_server( char *server_address, int port )
+{
+ const int on = 1;
+ int sock = -1;
+ struct addrinfo hints, *res, *ptr;
+ char portStr[6];
+
+ // Set hints for local addresses.
+ memset( &hints, 0, sizeof( hints ) );
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ snprintf( portStr, sizeof portStr, "%d", port );
+ if ( getaddrinfo( server_address, portStr, &hints, &res ) != 0 || res == NULL ) {
+ return false;
+ }
+ // Attempt to bind to all of the addresses as long as there's room in the poll list
+ for ( ptr = res; ptr != NULL; ptr = ptr->ai_next ) {
+ char bla[100];
+ if ( !sock_printable( ( struct sockaddr * ) ptr->ai_addr, ptr->ai_addrlen, bla, 100 ) ) {
+ snprintf( bla, 100, "[invalid]" );
+ }
+ printf( "Trying to connect to %s ", bla );
+ sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol );
+ if ( sock < 0 ) {
+ printf( "...cannot create socket, errno=%d\n", errno );
+ sock = -1;
+ continue;
+ }
+ setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof( on ) );
+ if ( ptr->ai_family == PF_INET6 ) {
+ setsockopt( sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof( on ) );
+ }
+ if ( connect( sock, ptr->ai_addr, ptr->ai_addrlen ) < 0 ) {
+ // if ( bind( sock, ptr->ai_addr, ptr->ai_addrlen ) == -1 ) {
+ printf( "...socket Error, errno=%d\n", errno );
+ close( sock );
+ sock = -1;
+ continue;
+ } else {
+ printf( "... connecting successful!\n" );
+ break;
+ }
+ }
+
+ freeaddrinfo( res );
+ return sock;
+}
+
diff --git a/src/fuse/imageHelper.h b/src/fuse/helper.h
index 60805cd..1c972e4 100755..100644
--- a/src/fuse/imageHelper.h
+++ b/src/fuse/helper.h
@@ -1,8 +1,8 @@
#ifndef IMAGEHELPER_H
#define IMAGEHELPER_H
+#include "../protocol.h"
#include <netdb.h>
-#include "protocol.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
@@ -12,10 +12,10 @@
typedef struct log_info {
- uint64_t imageSize;
- uint64_t receivedBytes;
- uint64_t imageBlockCount;
- uint8_t * blockRequestCount;
+ uint64_t imageSize;
+ uint64_t receivedBytes;
+ uint64_t imageBlockCount;
+ uint8_t *blockRequestCount;
} log_info;
@@ -24,5 +24,6 @@ void printLog(log_info *info);
bool sock_printable(struct sockaddr *addr, socklen_t addrLen, char *output, int len);
-int connect_to_server(char ** server_adress, int * port);
+int connect_to_server(char *server_adress, int port);
+
#endif
diff --git a/src/fuse/imageFuse.c b/src/fuse/imageFuse.c
deleted file mode 100755
index 2874b79..0000000
--- a/src/fuse/imageFuse.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * FUSE: Filesystem in Userspace
- * Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
- * This program can be distributed under the terms of the GNU GPL.
- * See the file COPYING.
- *
- * Changed by Stephan Schwaer
- * */
-
-#define FUSE_USE_VERSION 30
-#include <fuse.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-/* for socket */
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include "protocol.h"
-#include "serialize.h"
-/* for printing uint */
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
-#include "imageHelper.h"
-
-/* variables for socket */
-int sock = -1;
-int n;
-
-char* server_adress = NULL;
-int portno = -1;
-char* image_Name = NULL;
-char* imagePathName = NULL;
-uint16_t rid;
-uint8_t flags8;
-char buffer[1000];
-static uint64_t imageSize;
-/* Debug/Benchmark variables */
-bool useDebug = false;
-bool useLog = false;
-log_info logInfo;
-uint8_t printCount = 0;
-
-void error(const char *msg)
-{
- perror(msg);
- exit(0);
-}
-
-static int image_getattr(const char *path, struct stat *stbuf)
-{
- int res = 0;
- memset(stbuf, 0, sizeof(struct stat));
- if (strcmp(path, "/") == 0) {
- stbuf->st_mode = S_IFDIR | 0755;
- stbuf->st_nlink = 2;
- } else if (strcmp(path, imagePathName) == 0) {
- stbuf->st_mode = S_IFREG | 0755;
- stbuf->st_nlink = 1;
- stbuf->st_size = imageSize;
- } else
- res = -ENOENT;
- return res;
-}
-
-static int image_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
- off_t offset, struct fuse_file_info *fi)
-{
- (void) offset;
- (void) fi;
- if (strcmp(path, "/") != 0)
- return -ENOENT;
- filler(buf, ".", NULL, 0);
- filler(buf, "..", NULL, 0);
- filler(buf, imagePathName + 1, NULL, 0);
- return 0;
-}
-
-static int image_open(const char *path, struct fuse_file_info *fi)
-{
- if (strcmp(path, imagePathName) != 0)
- return -ENOENT;
- if ((fi->flags & 3) != O_RDONLY)
- return -EACCES;
- return 0;
-}
-
-static int image_read(const char *path, char *buf, size_t size, off_t offset,
- struct fuse_file_info *fi)
-{
- size_t len;
- /* buffer for throwing away unwanted messages. */
- char tBuf[100];
-
- (void) fi;
- if(strcmp(path, imagePathName) != 0)
- return -ENOENT;
- len = imageSize;
- if (offset < len) {
- if (offset + size > len)
- size = len - offset;
-
-get_block:
- /* seek inside the image */
- if(!dnbd3_get_block(sock, offset, size, offset)){
- printf("[ERROR] Get block error!\n");}
- else {
- printf("Get block success!\n");
- }
-
- /* count the requested blocks */
- uint64_t startBlock = offset / (4096);
- uint64_t endBlock = (offset + size - 1) / (4096);
-
- printf("StartBlockRequest: %"PRIu64"\n", startBlock);
- printf("EndBlockRequest: %"PRIu64"\n", endBlock);
-
- if(useDebug) {
- for (; startBlock <= endBlock; startBlock++){
- logInfo.blockRequestCount[startBlock] += 1;
- }
- }
-
- dnbd3_reply_t reply;
-
- /*see if the received package is a requested block, throw away if not */
- while(true){
- if(!dnbd3_get_reply(sock, &reply)){
- printf("[ERROR] Reply error\n");
-
- /* Try to reconnect after reply error */
- printf("Reconnecting!\n");
- sock = connect_to_server(&server_adress, &portno);
-
- if (sock == -1){
- printf("[ERROR] Connection Error!");
- exit(1);
- }
-
- printf("Selecting image ");
-
- bzero(buffer,256);
- rid = 0;
- flags8 = 0;
- serialized_buffer_t sbuffer;
- uint16_t protocol_version;
- char *name;
- uint16_t rrid;
-
- if(dnbd3_select_image(sock, image_Name, rid, flags8) != 1){
- printf("- Error\n");
- } else {printf("- Success\n");
- }
-
- if(!dnbd3_select_image_reply(&sbuffer, sock, &protocol_version, &name, &rrid, &imageSize)) {
- printf("Error reading reply\n");
- exit(1);
- } else {printf("Reply successful\n");
- }
-
- printf("Protocol version: %i, Image: %s, RevisionID: %i, Size: %i MiB\n",(int) protocol_version, name, (int) rrid,(int) (imageSize/(1024*1024)));
- goto get_block;
-
- } else {
- printf("Reply success\n");
- }
- if(reply.cmd == CMD_ERROR) {
- printf("Got a CMD_ERROR!\n");
- exit(1);
- }
- if(reply.cmd != CMD_GET_BLOCK) {
- printf("Received block isn't a wanted block, throwing it away...\n");
- int tDone = 0;
- int todo;
- while(tDone < reply.size){
- todo = reply.size - tDone > 100 ? 100: reply.size - tDone;
-
- n = read(sock, tBuf, todo);
- if (n <= 0) {
- if(n < 0 && (errno == EAGAIN || errno == EINTR)) continue;
- printf("[ERROR] Errno %i and %i\n",errno, n);
- exit(1);
- }
- tDone += n ;
- }
- continue;
- }
- break;
- }
-
- printf("Payloadsize: %i\n",(int) reply.size);
- printf("Offset: %"PRIu64"\n", reply.handle);
-
- if(size != reply.size){
- printf("Size: %i, reply.size: %i!\n",(int) size,(int) reply.size);
- exit(1);
- }
- /* read the data block data from received package */
- int done = 0;
- while (done < size ){
- n = read(sock, buf + done, size - done);
- if (n <= 0) {
- if(n < 0 && (errno == EAGAIN || errno == EINTR)) continue;
- printf("[ERROR] Error: %i and %i\n",errno, n);
- exit(1);
- }
- done += n;
- /* for benchmarking */
- logInfo.receivedBytes += n;
- }
- } else
- size = 0;
- printf("Received bytes: %i MiB\n",(int) (logInfo.receivedBytes/(1024*1024)));
-
- /* logfile stuff */
- if( useLog ){
- if (printCount == 0){
- printLog(&logInfo);
- }
- printCount = printCount + 1 % 100;
- }
- return size;
-}
-
-/* close the connection */
-void image_destroy(void* private_data){
- if ( useLog ){
- printLog(&logInfo);
- }
- if (close(sock) != 0) {
- printf("error closing file.\n");
- exit(-1);
- }
- free(imagePathName);
- return;
-}
-
-/* map the implemented fuse operations */
-static struct fuse_operations image_oper = {
- .getattr = image_getattr,
- .readdir = image_readdir,
- .open = image_open,
- .read = image_read,
- .destroy = image_destroy,
-};
-
-int main (int argc, char *argv[])
-{
- char* mountPoint = NULL;
- int opt;
- bool testOpt = false;
-
- if(argc == 1 ||strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "--usage") == 0 ){
-exit_usage:
- printf("Usage: %s [-l] [-d] [-t] -m <mountpoint> -s <serverAdress> -p <port> -i <imageName>\n", argv[0]);
- printf(" -l: creates a logfile log.txt at program path\n");
- printf(" -d: fuse debug mode\n");
- printf(" -t: use hardcoded server, port and image for testing\n");
- exit(EXIT_FAILURE);
- }
-
- while((opt = getopt(argc,argv,"m:s:p:i:tdl")) != -1){
- switch(opt) {
- case 'm':
- mountPoint = optarg;
- break;
- case 's':
- server_adress = optarg;
- break;
- case 'p':
- portno = atoi(optarg);
- break;
- case 'i':
- image_Name = optarg;
- break;
- case 't':
- testOpt = true;
- break;
- case 'd':
- useDebug = true;
- break;
- case 'l':
- useLog = true;
- useDebug = true;
- break;
- default:
- goto exit_usage;
- }
- }
-
- if(testOpt){
- /* values for testing. */
- server_adress = "132.230.4.1";
- portno = 5003;
- image_Name = "windows7-umwelt.vmdk";
- useLog = true;
- }
-
- if(server_adress == NULL || portno == -1 || image_Name == NULL || mountPoint == NULL){
- goto exit_usage;
- }
-
- int arg_count = 5;
- if (useDebug){
- arg_count++;
- }
- char * args[6] = {"foo", "-o", "ro,allow_other", "-s", mountPoint, "-d"};
-
- sock = connect_to_server(&server_adress, &portno);
-
- if (sock == -1){
- printf("[ERROR] Connection Error!");
- exit(1);
- }
-
- printf("Selecting image ");
-
- bzero(buffer,256);
- rid = 0;
- flags8 = 0;
-
- serialized_buffer_t sbuffer;
- uint16_t protocol_version;
- char *name;
- uint16_t rrid;
-
- if(dnbd3_select_image(sock, image_Name, rid, flags8) != 1){
- printf("- Error\n");
- } else {printf("- Success\n");
- }
-
- if(!dnbd3_select_image_reply(&sbuffer, sock, &protocol_version, &name, &rrid, &imageSize)) {
- printf("Error reading reply\n");
- exit(1);
- } else {printf("Reply successful\n");
- }
-
- printf("Protocol version: %i, Image: %s, RevisionID: %i, Size: %i MiB\n",(int) protocol_version, name, (int) rrid,(int) (imageSize/(1024*1024)));
-
- /* fix name of image if it contains '/' */
- int len = strlen(image_Name) - 1;
- bool fixName = false;
- for(; len >= 0; len--){
- if(image_Name[len] == '/'){
- fixName = true;
- break;
- }
- }
- if( fixName) {
- memmove(image_Name, image_Name + len + 1, strlen(image_Name) - len);
- printf("image_Name: %s\n", image_Name);
- }
-
-
- char * str1 = "/";
- char * tmpStr = (char *) malloc(1 + strlen(str1) + strlen(image_Name));
- strcpy(tmpStr, str1);
- strcat(tmpStr, image_Name);
- imagePathName = tmpStr;
-
- /* initialize benchmark variables */
- logInfo.receivedBytes = 0;
- logInfo.imageSize = imageSize;
- logInfo.imageBlockCount = imageSize % 4096 == 0 ? imageSize/(4096) : imageSize/(4096) + 1;
-
- uint8_t tmpShrt[logInfo.imageBlockCount];
- uint64_t i = 0;
- if ( useLog ){
- for(; i < logInfo.imageBlockCount; i++){
- tmpShrt[i] = 0;
- }
- }
-
- logInfo.blockRequestCount = tmpShrt;
-
- printf("ImagePathName: %s\n",imagePathName);
- return fuse_main(arg_count, args, &image_oper, NULL);
-}
-
-
diff --git a/src/fuse/imageHelper.c b/src/fuse/imageHelper.c
deleted file mode 100755
index b5bc9bd..0000000
--- a/src/fuse/imageHelper.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Helper functions for imageFuse
- * by Stephan Schwaer, January 2014
- */
-
-#include "imageHelper.h"
-void printLog(log_info *info){
- FILE *logFile;
-
- // Create logfile
-
- logFile = fopen("log.txt", "w+");
- if ( logFile == NULL) {
- printf("Error creating/opening log.txt\n");
- return;
- }
-
- //rewind(file);
- fprintf(logFile, "ImageSize: %"PRIu64" MiB\n", (uint64_t)(info->imageSize/(1024ll*1024ll)));
- fprintf(logFile, "ReceivedMiB: %"PRIu64" MiB\n", (uint64_t)(info->receivedBytes/(1024ll*1024ll)));
- fprintf(logFile, "imageBlockCount: %"PRIu64"\n", info->imageBlockCount);
- fprintf(logFile, "Blocksize: 4KiB\n\n");
- fprintf(logFile, "Block access count:\n");
-
- uint64_t i = 0;
- for (; i < info->imageBlockCount; i++){
- if( i % 50 == 0 ) fprintf(logFile, "\n");
- fprintf(logFile, "%i ",(int) info->blockRequestCount[i]);
- }
- fprintf(logFile, "\n");
- fclose(logFile);
-}
-
-bool sock_printable(struct sockaddr *addr, socklen_t addrLen, char *output, int len)
-{
- char host[100], port[10];
- int ret = getnameinfo( addr, addrLen, host, 100, port, 10, NI_NUMERICHOST | NI_NUMERICSERV );
- if ( ret == 0 ) snprintf( output, len, "[%s]:%s", host, port );
- return ret == 0;
-}
-
-
-int connect_to_server(char ** server_adress, int * port){
- const int on = 1;
- int sock = -1;
- struct addrinfo hints, *res, *ptr;
- char portStr[6];
-
- // Set hints for local addresses.
- memset( &hints, 0, sizeof(hints) );
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- snprintf( portStr, sizeof portStr, "%d", *port );
- if ( getaddrinfo( *server_adress, portStr, &hints, &res ) != 0 || res == NULL ) return false;
- // Attempt to bind to all of the addresses as long as there's room in the poll list
- for( ptr = res; ptr != NULL; ptr = ptr->ai_next ) {
- char bla[100];
- if ( !sock_printable( (struct sockaddr*)ptr->ai_addr, ptr->ai_addrlen, bla, 100 ) ) snprintf( bla, 100, "[invalid]" );
- printf( "Trying to connect to %s ", bla );
- sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol );
- if ( sock < 0 ) {
- printf( "...cannot create socket, errno=%d\n", errno );
- sock = -1;
- continue;
- }
- setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
- if ( ptr->ai_family == PF_INET6 ) setsockopt( sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on) );
- if (connect(sock, ptr->ai_addr, ptr->ai_addrlen) < 0) {
- // if ( bind( sock, ptr->ai_addr, ptr->ai_addrlen ) == -1 ) {
- printf( "...socket Error, errno=%d\n", errno );
- close( sock );
- sock = -1;
- continue;
- } else {
- printf( "... connecting successful!\n");
- break;
- }
- }
-
- freeaddrinfo( res );
- return sock;
-}
-
diff --git a/src/fuse/main.c b/src/fuse/main.c
new file mode 100644
index 0000000..79f17e8
--- /dev/null
+++ b/src/fuse/main.c
@@ -0,0 +1,348 @@
+/*
+ * FUSE: Filesystem in Userspace
+ * Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+ * This program can be distributed under the terms of the GNU GPL.
+ * See the file COPYING.
+ *
+ * Changed by Stephan Schwaer
+ * */
+
+#include "../protocol.h"
+#include "../serialize.h"
+#include "helper.h"
+
+#define FUSE_USE_VERSION 30
+#include <fuse.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+/* for socket */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+/* for printing uint */
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+/* variables for socket */
+int sock = -1;
+int n;
+
+char *server_address = NULL;
+int portno = -1;
+char *image_Name = NULL;
+const char *imagePathName = "/image";
+uint16_t rid;
+static uint64_t imageSize;
+/* Debug/Benchmark variables */
+bool useDebug = false;
+bool useLog = false;
+log_info logInfo;
+uint8_t printCount = 0;
+
+void error(const char *msg)
+{
+ perror( msg );
+ exit( 0 );
+}
+
+static void dnbd3_connect()
+{
+ while ( true ) {
+ if ( sock != -1 ) {
+ close( sock );
+ }
+ sock = connect_to_server( server_address, portno );
+
+ if ( sock == -1 ) {
+ printf( "[ERROR] Connection Error!\n" );
+ goto fail;
+ }
+
+ printf( "Selecting image " );
+
+ serialized_buffer_t sbuffer;
+ uint16_t protocol_version;
+ char *name;
+ uint16_t rrid;
+
+ if ( dnbd3_select_image( sock, image_Name, rid, 0 ) != 1 ) {
+ printf( "- Error\n" );
+ goto fail;
+ }
+ printf( "- Success\n" );
+
+ if ( !dnbd3_select_image_reply( &sbuffer, sock, &protocol_version, &name, &rrid, &imageSize ) ) {
+ printf( "Error reading reply\n" );
+ goto fail;
+ }
+ printf( "Reply successful\n" );
+
+ if ( rid != 0 && rid != rrid ) {
+ printf( "Got unexpected rid %d, wanted %d\n", (int)rrid, (int)rid );
+ sleep( 10 );
+ goto fail;
+ }
+ rid = rrid;
+
+ printf( "Protocol version: %i, Image: %s, RevisionID: %i, Size: %i MiB\n", (int)protocol_version, name, (int) rrid, (int)( imageSize/ ( 1024*1024 ) ) );
+ return;
+
+fail: ;
+ sleep( 2 );
+ }
+}
+
+static int image_getattr(const char *path, struct stat *stbuf)
+{
+ int res = 0;
+ memset( stbuf, 0, sizeof( struct stat ) );
+ if ( strcmp( path, "/" ) == 0 ) {
+ stbuf->st_mode = S_IFDIR | 0755;
+ stbuf->st_nlink = 2;
+ } else if ( strcmp( path, imagePathName ) == 0 ) {
+ stbuf->st_mode = S_IFREG | 0755;
+ stbuf->st_nlink = 1;
+ stbuf->st_size = imageSize;
+ } else {
+ res = -ENOENT;
+ }
+ return res;
+}
+
+static int image_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset UNUSED, struct fuse_file_info *fi UNUSED)
+{
+ if ( strcmp( path, "/" ) != 0 ) {
+ return -ENOENT;
+ }
+ filler( buf, ".", NULL, 0 );
+ filler( buf, "..", NULL, 0 );
+ filler( buf, imagePathName + 1, NULL, 0 );
+ return 0;
+}
+
+static int image_open(const char *path, struct fuse_file_info *fi)
+{
+ if ( strcmp( path, imagePathName ) != 0 ) {
+ return -ENOENT;
+ }
+ if ( ( fi->flags & 3 ) != O_RDONLY ) {
+ return -EACCES;
+ }
+ return 0;
+}
+
+static int image_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi UNUSED)
+{
+ /* buffer for throwing away unwanted messages. */
+ char tBuf[100];
+
+ if ( strcmp( path, imagePathName ) != 0 ) {
+ return -ENOENT;
+ }
+ if ( offset >= imageSize ) {
+ return 0;
+ }
+ if ( offset + size > imageSize ) {
+ size = imageSize - offset;
+ }
+
+ if ( sock == -1 ) {
+retry: ;
+ dnbd3_connect();
+ }
+
+ /* seek inside the image */
+ if ( !dnbd3_get_block( sock, offset, size, offset ) ) {
+ printf( "[ERROR] Get block error!\n" );
+ goto retry;
+ }
+
+ /* count the requested blocks */
+ uint64_t startBlock = offset / ( 4096 );
+ uint64_t endBlock = ( offset + size - 1 ) / ( 4096 );
+
+ printf( "StartBlockRequest: %"PRIu64"\n", startBlock );
+ printf( "EndBlockRequest: %"PRIu64"\n", endBlock );
+
+ if ( useDebug ) {
+ for ( ; startBlock <= endBlock; startBlock++ ) {
+ logInfo.blockRequestCount[startBlock] += 1;
+ }
+ }
+
+ dnbd3_reply_t reply;
+
+ /*see if the received package is a requested block, throw away if not */
+ while ( true ) {
+ if ( !dnbd3_get_reply( sock, &reply ) ) {
+ printf( "[ERROR] Reply error\n" );
+ goto retry;
+ }
+ printf( "Reply success\n" );
+
+ if ( reply.cmd == CMD_ERROR ) {
+ printf( "Got a CMD_ERROR!\n" );
+ goto retry;
+ }
+ if ( reply.cmd != CMD_GET_BLOCK ) {
+ printf( "Received block isn't a wanted block, throwing it away...\n" );
+ int tDone = 0;
+ int todo;
+ while ( tDone < reply.size ) {
+ todo = reply.size - tDone > 100 ? 100: reply.size - tDone;
+
+ n = read( sock, tBuf, todo );
+ if ( n <= 0 ) {
+ if ( n < 0 && ( errno == EAGAIN || errno == EINTR ) ) {
+ continue;
+ }
+ printf( "[ERROR] Errno %i and %i\n",errno, n );
+ goto retry;
+ }
+ tDone += n;
+ }
+ continue;
+ }
+ break;
+ }
+
+ printf( "Payloadsize: %i\n", ( int ) reply.size );
+ printf( "Offset: %"PRIu64"\n", reply.handle );
+
+ if ( size != reply.size || offset != reply.handle ) {
+ printf( "Size: %i, reply.size: %i!\n", ( int ) size, ( int ) reply.size );
+ printf( "Handle: %" PRIu64 ", reply.handle: %" PRIu64 "!\n", offset, reply.handle );
+ goto retry;
+ }
+ /* read the data block data from received package */
+ int done = 0;
+ while ( done < size ) {
+ n = read( sock, buf + done, size - done );
+ if ( n <= 0 ) {
+ if ( n < 0 && ( errno == EAGAIN || errno == EINTR ) ) {
+ continue;
+ }
+ printf( "[ERROR] Error: %i and %i\n",errno, n );
+ goto retry;
+ }
+ done += n;
+ /* for benchmarking */
+ logInfo.receivedBytes += n;
+ }
+ printf( "Received bytes: %i MiB\n", ( int )( logInfo.receivedBytes/ ( 1024*1024 ) ) );
+
+ /* logfile stuff */
+ if ( useLog ) {
+ if ( printCount == 0 ) {
+ printLog( &logInfo );
+ }
+ printCount++;
+ }
+ return size;
+}
+
+/* close the connection */
+void image_destroy(void *private_data)
+{
+ if ( useLog ) {
+ printLog( &logInfo );
+ }
+ if ( sock != -1 ) {
+ close( sock );
+ sock = -1;
+ }
+ return;
+}
+
+/* map the implemented fuse operations */
+static struct fuse_operations image_oper = {
+ .getattr = image_getattr,
+ .readdir = image_readdir,
+ .open = image_open,
+ .read = image_read,
+ .destroy = image_destroy,
+};
+
+int main(int argc, char *argv[])
+{
+ char *mountPoint = NULL;
+ int opt;
+ bool testOpt = false;
+
+ if ( argc == 1 || strcmp( argv[1], "--help" ) == 0 || strcmp( argv[1], "--usage" ) == 0 ) {
+exit_usage:
+ printf( "Usage: %s [-l] [-d] [-t] -m <mountpoint> -s <serverAdress> -p <port> -i <imageName>\n", argv[0] );
+ printf( " -l: creates a logfile log.txt at program path\n" );
+ printf( " -d: fuse debug mode\n" );
+ printf( " -t: use hardcoded server, port and image for testing\n" );
+ exit( EXIT_FAILURE );
+ }
+
+ while ( ( opt = getopt( argc,argv,"m:s:p:i:tdl" ) ) != -1 ) {
+ switch ( opt ) {
+ case 'm':
+ mountPoint = optarg;
+ break;
+ case 's':
+ server_address = optarg;
+ break;
+ case 'p':
+ portno = atoi( optarg );
+ break;
+ case 'i':
+ image_Name = optarg;
+ break;
+ case 't':
+ testOpt = true;
+ break;
+ case 'd':
+ useDebug = true;
+ break;
+ case 'l':
+ useLog = true;
+ useDebug = true;
+ break;
+ default:
+ goto exit_usage;
+ }
+ }
+
+ if ( testOpt ) {
+ /* values for testing. */
+ server_address = "132.230.4.1";
+ portno = 5003;
+ image_Name = "windows7-umwelt.vmdk";
+ useLog = true;
+ }
+
+ if ( server_address == NULL || portno == -1 || image_Name == NULL || mountPoint == NULL ) {
+ goto exit_usage;
+ }
+
+ int arg_count = 5;
+ if ( useDebug ) {
+ arg_count++;
+ }
+ char *args[6] = {"foo", "-o", "ro,allow_other", "-s", mountPoint, "-d"};
+
+ dnbd3_connect();
+
+ /* initialize benchmark variables */
+ logInfo.receivedBytes = 0;
+ logInfo.imageSize = imageSize;
+ logInfo.imageBlockCount = ( imageSize + 4095 ) / 4096;
+
+ uint8_t tmpShrt[logInfo.imageBlockCount];
+ memset( tmpShrt, 0, sizeof tmpShrt );
+
+ logInfo.blockRequestCount = tmpShrt;
+
+ printf( "ImagePathName: %s\n",imagePathName );
+ return fuse_main( arg_count, args, &image_oper, NULL );
+}
+
diff --git a/src/fuse/serialize.c b/src/fuse/serialize.c
new file mode 100644
index 0000000..4934132
--- /dev/null
+++ b/src/fuse/serialize.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../serialize.c"
diff --git a/src/server/protocol.h b/src/protocol.h
index 41c6410..d119dc5 100644
--- a/src/server/protocol.h
+++ b/src/protocol.h
@@ -1,9 +1,11 @@
#ifndef _PROTOCOL_H_
#define _PROTOCOL_H_
-#include "../types.h"
-#include "../serialize.h"
+#include <sys/types.h>
+#include <sys/socket.h>
#include <errno.h>
+#include "types.h"
+#include "serialize.h"
#define FLAGS8_SERVER (1)
diff --git a/src/serialize.h b/src/serialize.h
index b6ce145..14d3d13 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -1,6 +1,7 @@
#ifndef SERIALIZER_H_
#define SERIALIZER_H_
+// Careful with includes - this is used in kernel module too
#include "config.h"
typedef struct
diff --git a/src/server/altservers.c b/src/server/altservers.c
index c7e2297..99cbdec 100644
--- a/src/server/altservers.c
+++ b/src/server/altservers.c
@@ -8,6 +8,7 @@
#include "image.h"
#include "signal.h"
#include "log.h"
+#include "../protocol.h"
#include <stdlib.h>
#include <unistd.h>
#include <sys/errno.h>
@@ -16,7 +17,6 @@
#include <inttypes.h>
#include <time.h>
#include <stdio.h>
-#include "protocol.h"
static dnbd3_connection_t *pending[SERVER_MAX_PENDING_ALT_CHECKS];
static pthread_spinlock_t pendingLockProduce; // Lock for adding something to pending. (NULL -> nonNULL)
diff --git a/src/server/image.c b/src/server/image.c
index b86ecf3..f552843 100644
--- a/src/server/image.c
+++ b/src/server/image.c
@@ -5,7 +5,7 @@
#include "uplink.h"
#include "locks.h"
#include "integrity.h"
-#include "protocol.h"
+#include "../protocol.h"
#include "sockhelper.h"
#include "altservers.h"
#include "server.h"
diff --git a/src/server/uplink.c b/src/server/uplink.c
index d71daa6..469ac4a 100644
--- a/src/server/uplink.c
+++ b/src/server/uplink.c
@@ -6,7 +6,7 @@
#include "helper.h"
#include "altservers.h"
#include "helper.h"
-#include "protocol.h"
+#include "../protocol.h"
#include "signal.h"
#include <pthread.h>