Ejemplo n.º 1
0
/**
 * This is used by the client application program to unmount a previously mounted file system
 * @param  localFolderName local name of the folder given to the mounted files
 * @return                 0 on success and -1 otherwise
 */
int fsUnmount(const char *localFolderName) {
	// 	the counterpart of fsMount() 
	// 	to unmount a remote filesystem that is referred to locally by localFolderName. 
	// 	Returns 0 on success, −1 on failure with errno set appropriately
	remote_folder_server *serverToUnmount = findServerByFolderName(localFolderName);
	// printf("serverName: %s, serverPort: %i, clientID: %i\n", serverToUnmount->srvIpOrDomName, serverToUnmount->srvPort, *serverToUnmount->clientId);
	return_type ans = make_remote_call( serverToUnmount->srvIpOrDomName,
										serverToUnmount->srvPort,
										"fsUnmount", 2,
										strlen(localFolderName), (void *)(localFolderName),
										sizeof(int), (void *)(serverToUnmount->clientId));
	
	int result = *(int*)(ans.return_val);

	if (result != 0) {
		errno = result;
		return -1;
	}

	if (removeServerByFolderName(localFolderName) == -1) {
		return -1;
	}

	return result;
}
Ejemplo n.º 2
0
/**
 * Opens the folder folder_name that is presumably the local name of
 * a folder that has been mounted previously. Returns a NULL if an error occurs.
 *
 * @param folder_name name of the directory
 * @return            struct containing details about the directory, NULL if failure
 */
FSDIR* fsOpenDir(const char *folder_name) {
    struct mount_info *info = mount_info_list_find(folder_name, false);
    if (info == NULL) {
        errno = ENOENT;
        return NULL;
    }

    char *relpath = relative_path_from_mount_path(folder_name, info->local_folder_name);
    if (relpath == NULL) {
        errno = ENOENT;
        return NULL;
    }

    return_type ans = make_remote_call(info->ip_or_domain,
                                       info->port_no, "fsOpenDir", 1,
                                       strlen(relpath) + 1, (void *) relpath);

    fs_response *response = (fs_response *)ans.return_val;
    FSDIR *fsdirp = NULL;
    if (!handle_possible_error(response)) {
        fsdirp = (FSDIR *)malloc(sizeof(FSDIR));
        fsdirp->dirp = *(DIR **)response->retval;
        fsdirp->mount_info = info;
    }

    free(relpath);
    free(response);
    return fsdirp;
}
Ejemplo n.º 3
0
/**
 * Removes (i.e., deletes) this file or folder from the server.
 *
 * @param name of file or folder to be removed
 * @return     0 on success, −1 on failure
 */
int fsRemove(const char *name) {
    struct mount_info *info = mount_info_list_find(name, false);
    if (info == NULL) {
        errno = ENOENT;
        return -1;
    }

    char * relpath = relative_path_from_mount_path(name, info->local_folder_name);

    if (strcmp(relpath, "/") == 0) {
        free(relpath);
        errno = EBUSY;
        return -1;
    }

    return_type ans = make_remote_call(info->ip_or_domain,
                                       info->port_no, "fsRemove", 1,
                                       strlen(relpath) + 1, (void *)relpath);
    fs_response *response = (fs_response *)ans.return_val;

    int retval = *(int *)response->retval;
    handle_possible_error(response);

    free(relpath);
    free(response);
    return retval;
}
Ejemplo n.º 4
0
/**
 * Reads up to "count" bytes in to the supplied buffer buf from the file referred
 * to by the file descriptor fd, which was presumably the return from a call to
 * fsOpen() in read-mode.
 *
 * @param fd    file descriptor of file to be read
 * @param buf   buffer for data to be written to
 * @param count number of bytes to be read
 * @return      0 on success, −1 on failure
 */
int fsRead(int fd, void *buf, const unsigned int count) {
    struct fd_entry *current = fd_entry_list_find(fd);

    if (current == NULL) {
        errno = EBADF;
        return -1;
    }

    return_type ans = make_remote_call(current->mount_info->ip_or_domain,
                                       current->mount_info->port_no, "fsRead", 2,
                                       sizeof(int), (void *) &fd,
                                       sizeof(int), (void *) &count);

    int inerror = *(int *)ans.return_val;
    if (inerror) {
        int _errno = *(int *)(ans.return_val + sizeof(int));
        errno = _errno;
        free(ans.return_val);
        return -1;
    }

    int bytesread = *(int *)(ans.return_val + (2 * sizeof(int)));
    memcpy(buf, ans.return_val + (3 * sizeof(int)), bytesread);
    free(ans.return_val);
    return bytesread;
}
Ejemplo n.º 5
0
/**
 * This is used by the client application program to open a remote file
 * @param  fname Name of the remote file to open
 * @param  mode  Mode in which to open the remote file, 
 * 1 for write permission and 0 for read permissions
 * @return       File descriptor number, positive integer, -1 on error
 */
int fsOpen(const char *fname, int mode) {
	#ifdef _DEBUG_CLI_
	printf("in fsOpen\n");
	#endif

	remote_folder_server *server;
	if ((server = findServerByFolderName(fname)) == NULL) {
		errno = ENOENT;
		return -1;
	}
	
	while(1) {
		return_type ans = make_remote_call( server->srvIpOrDomName,
											server->srvPort,
											"fsOpen", 3,
											sizeof(int), (void *)(server->clientId),
											strlen(fname), (void *)(fname),
											sizeof(int), (void *)(&mode));
		if (ans.return_size == 0) {
			//error set errno
			#ifdef _DEBUG_CLI_
			printf("return_size zero: %d\n", ans.return_size);
			#endif
			errno = EBADMSG;
			return -1;
		} else {
			int *status = (int*)malloc(sizeof(int));
			memcpy( status, 
	                ans.return_val, 
	                sizeof(int));
			char * index = (char*)(ans.return_val);
			index += sizeof(int);
			// printf("status: %d\n", *status);
			int *val = (int*)malloc(sizeof(int));
			memcpy( val, 
	        	    index, 
	            	sizeof(int));
			if (*status == 0){
				#ifdef _DEBUG_CLI_
				printf("positive val: %d\n", *val);
				#endif
				int clientFd = createClientFd(fname, *val);
				return clientFd;
			} else if(*status == -2) {
				// printf("fsOpen client will start to sleep\n");
				usleep(100000);
			} else {
				errno = *val;
				#ifdef _DEBUG_CLI_
				printf("negative val: %d, errno: %s\n", *val, strerror(errno));
				#endif
				return -1;
			}
		}
	}
}
Ejemplo n.º 6
0
/**
 * This is used by the client application program to mount a remote server.
 * @param  srvIpOrDomName  the name or the IP address of the server to mount
 * @param  srvPort         port number in the server to mount
 * @param  localFolderName local name of the folder given to the mounted files
 * @return                 0 on success and -1 otherwise
 */
int fsMount(const char *srvIpOrDomName, const unsigned int srvPort, const char *localFolderName) {
	// do similar stuff as ass1 client app
	// save ip address and port number for subsequent remote calls

	#ifdef _DEBUG_CLI_
	printf("Calling fsMount to server\n");
	#endif

	remote_folder_server *newServer;
	if ((newServer = findServerByFolderName(localFolderName)) != NULL) {
		// printf("Server %s already exists as %s\n", localFolderName, newServer->localFolderName);
		errno = EEXIST;
		return -1;
	}

	return_type ans = make_remote_call( srvIpOrDomName,
										(int)srvPort,
										"fsMount", 1,
										strlen(localFolderName), (void *)(localFolderName));
	int containsError;
	int returnedValue;

	memcpy(&containsError, ans.return_val, sizeof(int));
	memcpy(&returnedValue, ans.return_val+sizeof(int), sizeof(int));
	
	if (containsError == 0) {
		//save id
		#ifdef _DEBUG_CLI_
		printf("Successfully returned, given clientID: %d\n", returnedValue);
		#endif
		
		newServer = (remote_folder_server*)malloc(sizeof(remote_folder_server));
		newServer->localFolderName = (char*)malloc(strlen(localFolderName));
		newServer->srvIpOrDomName  = (char*)malloc(strlen(srvIpOrDomName));
		newServer->clientId        = (int*) malloc(sizeof(int));

		*newServer->clientId = returnedValue;
		newServer->srvPort   = srvPort;
		newServer->next = NULL;

		strcpy(newServer->localFolderName, localFolderName);
		strcpy(newServer->srvIpOrDomName, srvIpOrDomName);

		addNewServer(newServer);

		return 0;
	}

	errno = returnedValue;

	return -1;
}
Ejemplo n.º 7
0
/**
 * This is used by the client application program to close a remote file
 * @param  fd File descriptor of the file to close
 * @return    0 on success, -1 otherwise
 */
int fsClose(int fd) {
	#ifdef _DEBUG_CLI_
	printf("in fsClose\n");
	#endif

	client_fd *clientFdNode;
	if ((clientFdNode = getNodeFromClientFd(fd)) == NULL) {
		errno = EBADF;
		return -1;
	}

	remote_folder_server *server;
	if ((server = findServerByFolderName(clientFdNode->localFolderName)) == NULL) {
		errno = ENOENT;
		return -1;
	}
	return_type ans = make_remote_call( server->srvIpOrDomName,
										server->srvPort,
										"fsClose", 2,
										sizeof(int), (void *)(server->clientId),
										sizeof(int), (void *)(&clientFdNode->serverFd));
	if (ans.return_size == 0) {
		//error set errno
		#ifdef _DEBUG_CLI_
		printf("return_size zero: %d\n", ans.return_size);
		#endif
		errno = EBADMSG;
		return -1;
	} else if (*(int*)(ans.return_val) != 0) {
		#ifdef _DEBUG_CLI_
		printf("return_val not zero: %s\n", strerror(*(int*)(ans.return_val)));
		#endif
		errno = *(int*)(ans.return_val);
		//set errno before returning using return_val as errno
		return -1;
	} else {
		#ifdef _DEBUG_CLI_
		printf("return_val should be zero: %d\n", *(int*)(ans.return_val));
		#endif
		if (removeClientFd(clientFdNode->clientFd) == 0) {
    		return 0;
		} else {
			#ifdef _DEBUG_CLI_
			printf("did not removeClientFd, return_size zero: %d\n", ans.return_size);
			#endif
			errno = EBADMSG;
			return -1;
		}
	}
}
Ejemplo n.º 8
0
int main()
{
    int a = -10, b = 25, c = 50;
    return_type ans = make_remote_call("129.97.56.15",
	                               10000,
                                   "addtwo", 3,
	                               sizeof(int), (void *)(&a),
	                               sizeof(int), (void *)(&b),
                                   sizeof(int), (void *)(&c));
    int i = *(int *)(ans.return_val);
    printf("client, got result: %d\n", i);

    return 0;
}
Ejemplo n.º 9
0
/**
 * Closes a directory.
 *
 * @param fsdirp details of the directory to be closed
 * @return       0 on success, −1 on failure
 */
int fsCloseDir(FSDIR *fsdirp) {
    const return_type ans = make_remote_call(fsdirp->mount_info->ip_or_domain,
                                       fsdirp->mount_info->port_no, "fsCloseDir", 1,
                                       sizeof(DIR *), (void *) &fsdirp->dirp);

    fs_response *response = (fs_response *)ans.return_val;
    int retval = *(int *)response->retval;
    if (!handle_possible_error(response)) {
        free(fsdirp);
    }

    free(response);
    return retval;
}
Ejemplo n.º 10
0
/**
 * Reads a directory. Returns NULL of an error occured.
 *
 * @param fsdirp details of the directory to be read
 * @return       fsDirent of the directory to be read.
 */
struct fsDirent *fsReadDir(FSDIR *fsdirp) {
    return_type ans = make_remote_call(fsdirp->mount_info->ip_or_domain,
                                       fsdirp->mount_info->port_no, "fsReadDir", 1,
                                       sizeof(DIR *), (void *) &fsdirp->dirp);

    fs_response *response = (fs_response *)ans.return_val;
    struct fsDirent *retval = NULL;
    if (!handle_possible_error(response)) {
        dent = *(struct fsDirent *)response->retval;
        retval = &dent;
    }

    free(response);
    return retval;
}
Ejemplo n.º 11
0
/**
 * This is used by the client application program to close
 * a directory in the remote file system
 * @param  folder Pointer to the remote folder to close
 * @return        0 on success -1 otherwise
 */
int fsCloseDir(FSDIR *folder) {
	remote_folder_server *server = findServerByFolderName(folder->folderName);
	
	// printf("in fsCloseDir, clientId: %d\n", *server->clientId);
	
	return_type ans = make_remote_call( server->srvIpOrDomName,
										server->srvPort ,
										"fsCloseDir", 1,
										sizeof(int), (void *)(server->clientId));

	// printf("return_size: %d\n", ans.return_size);
	// printf("return_val: %d\n", *(int*)(ans.return_val));

	if (ans.return_size == 0) {
		#ifdef _DEBUG_CLI_
		printf("return_size zero: %d\n", ans.return_size);
		#endif
	
		//set errno before returning using a generic error
		errno = EBADMSG;
		return -1;
	
	} else if (*(int*)(ans.return_val) != 0) {
		#ifdef _DEBUG_CLI_
		printf("return_val not zero: %s\n", strerror(*(int*)(ans.return_val)));
		#endif
	
		errno = *(int*)(ans.return_val);
	
		//set errno before returning using return_val as errno
		return -1;
	} else {
		
		#ifdef _DEBUG_CLI_
		printf("return_val should be zero: %d\n", *(int*)(ans.return_val));
		#endif

		free(folder);
		folder = NULL;

    	return 0;
	}
}
Ejemplo n.º 12
0
/**
 * This is used by the client application program to open 
 * a directory in the remote file system
 * @param  folderName Local name of the mounted folder 
 * @return            Pointer to the file system directory
 */
FSDIR* fsOpenDir(const char *folderName) {
	
	remote_folder_server *server;
	if ((server = findServerByFolderName(folderName)) == NULL) {
		errno = ENOENT;
		return NULL;
	}
	// printf("in fsOpenDir, clientId: %d, folderName: %s\n", *server->clientId, folderName);

	return_type ans = make_remote_call( server->srvIpOrDomName,
										server->srvPort,
										"fsOpenDir", 2,
										sizeof(int), (void *)(server->clientId),
										strlen(folderName), (void *)(folderName));
	// printf("return_size: %d\n", ans.return_size);
	// printf("return_val: %d\n", *(int*)(ans.return_val));
	if (ans.return_size == 0) {
		#ifdef _DEBUG_CLI_
		// printf("return_size zero: %d\n", ans.return_size);
		#endif
		FSDIR *nice = NULL;
		//set errno before returning using a generic error
		errno = EBADMSG;
		return nice;
	} else if (*(int*)(ans.return_val) != 0) {
		#ifdef _DEBUG_CLI_
		// printf("return_val not zero: %s\n", strerror(*(int*)(ans.return_val)));
		#endif
		//set errno before returning using return_val as errno
		FSDIR *nice = NULL;
		errno = *(int*)(ans.return_val);
		return nice;
	} else {

		FSDIR* result = malloc(sizeof(FSDIR));
		result->folderName = (char*)malloc(strlen(folderName));

		strcpy(result->folderName, folderName);
		result->id     = *server->clientId;
		result->status = *(int*)(ans.return_val);
    	return result;
	}
}
Ejemplo n.º 13
0
/**
 * Writes up to "count" bytes from buf into the file referred to with the file
 * descriptor fd that was presumably the return from an earlier fsOpen() call
 * in write-mode.
 *
 * @param fd    file descriptor of file to be written to
 * @param buf   buffer of data to be written
 * @param count number of bytes to be written
 * @return      0 on success, −1 on failure
 */
int fsWrite(int fd, const void *buf, const unsigned int count) {
    struct fd_entry *current = fd_entry_list_find(fd);

    if (current == NULL) {
        errno = EBADF;
        return -1;
    }

    return_type ans = make_remote_call(current->mount_info->ip_or_domain,
                                       current->mount_info->port_no, "fsWrite", 2,
                                       sizeof(int), (void *) &fd,
                                       count, (void *) buf);

    fs_response *response = (fs_response *)ans.return_val;
    int retval = *(int *)response->retval;
    handle_possible_error(response);
    free(response);
    return retval;
}
Ejemplo n.º 14
0
/**
 * Closes an open file.
 *
 * @param fd file descriptor of file to be closed
 * @return   0 on success, −1 on failure
 */
int fsClose(int fd) {
    struct fd_entry *current = fd_entry_list_find(fd);

    if (current == NULL) {
        errno = EBADF;
        return -1;
    }

    return_type ans = make_remote_call(current->mount_info->ip_or_domain,
                                       current->mount_info->port_no, "fsClose", 1,
                                       sizeof(int), (void *) &fd);

    fs_response *response = (fs_response *)ans.return_val;

    if (!handle_possible_error(response)) {
        fd_entry_list_delete(current);
    }

    int retval = *(int *)response->retval;
    free(response);
    return retval;
}
Ejemplo n.º 15
0
/**
 * Opens a file whose path is fname. The mode is one of two values: 0 for read,
 * and 1 for write. Returns a file descriptor that can be used in future calls for
 * operations on this file.
 *
 * @param fname path of file to be opened
 * @param mode  read mode. 0 for read, and 1 for write
 * @return       a file descriptor of the file. -1 if failure
 */
int fsOpen(const char *fname, int mode) {
    struct mount_info *info = mount_info_list_find(fname, false);
    if (info == NULL) {
        errno = ENOENT;
        return -1;
    }

    char *path = relative_path_from_mount_path(fname, info->local_folder_name);
    if (path == NULL) {
        errno = ENOENT;
        return -1;
    }

    return_type ans;
    int attempts = 0, retval;
    fs_response *response;
    do {
        if (attempts++ > 0) sleep(1);
        ans = make_remote_call(info->ip_or_domain,
                               info->port_no, "fsOpen", 2,
                               strlen(path) + 1, (void *) path,
                               sizeof(int), (void *) &mode);
        response = (fs_response *)ans.return_val;
    } while (*(int *)response->retval == FS_OPEN_WAIT_MSG);


    int fd = *(int *)response->retval;
    if (!handle_possible_error(response)) {
        struct fd_entry *entry = (struct fd_entry *)malloc(sizeof(struct fd_entry));
        entry->fd = fd;
        entry->mount_info = info;
        entry->next = NULL;
        fd_entry_list_insert(entry);
    }

    free(path);
    free(response);
    return fd;
}
Ejemplo n.º 16
0
/**
 * This is used by the client application program to write to a remote file
 * @param  fd    File descriptor of the file to read from
 * @param  buf   Pointer to a buffer to hold the content to write to the file
 * @param  count Size of the buffer to read
 * @return       Number of bytes actually written, -1 on error
 */
int fsWrite(int fd, const void *buf, const unsigned int count) {
	#ifdef _DEBUG_CLI_
	printf("in fsWrite\n");
	#endif
	client_fd *clientFdNode = getNodeFromClientFd(fd);
	remote_folder_server *server = findServerByFolderName(clientFdNode->localFolderName);
	return_type ans = make_remote_call( server->srvIpOrDomName,
										server->srvPort,
										"fsWrite", 2,
										sizeof(int), (void*)(&(clientFdNode->serverFd)),
										count, buf);
	int errorDescriptor;
	int returnedValue;

	if (ans.return_size == 0) {
		//error set errno
		#ifdef _DEBUG_CLI_
		printf("return_size zero: %d\n", ans.return_size);
		#endif
		errno = EBADMSG;
		return -1;
	} else if (ans.return_size == 2*sizeof(int)) {
		
		memcpy(&errorDescriptor, ans.return_val, sizeof(int));
		memcpy(&returnedValue, ans.return_val+sizeof(int), sizeof(int));
	} else {
		#ifdef _DEBUG_CLI_
		printf("\tUnrecognized return value from server\n");
		#endif
		return -1;
	}

	if (errorDescriptor == -1) {
		errno = returnedValue;
		return -1;
	}

	return returnedValue;
}
Ejemplo n.º 17
0
/**
 * This is used by the client application program to remove a remote file
 * @param  name Name of the file to remove
 * @return      0 on success, -1 otherwise
 */
int fsRemove(const char *name) {
    #ifdef _DEBUG_CLI_
	printf("in fsRemove\n");
	#endif
	remote_folder_server *server = findServerByFolderName(name);
	while(1) {
		return_type ans = make_remote_call( server->srvIpOrDomName,
											server->srvPort,
											"fsRemove", 2,
											sizeof(int), (void *)(server->clientId),
											strlen(name), name);

		if (ans.return_size != sizeof(int)) {
			#ifdef _DEBUG_CLI_
			printf("\treturn_size bad: %d\n", ans.return_size);
			#endif
			errno = EBADMSG;
			return -1;
		} else if (*(int*)ans.return_val == -2) {
			#ifdef _DEBUG_CLI_
			printf("client will start to sleep\n");
			#endif
			usleep(100000);
		} else if (*(int*)ans.return_val != 0) {
			#ifdef _DEBUG_CLI_
			printf("\tError when deleting file\n");
			#endif

			errno = *(int*)ans.return_val;
			perror("fsRemove");
			return -1;
		} else if (*(int*)ans.return_val == 0) {
			removeClientFdByName(name);
			return 0;
		}
	}
	return 0;
}
Ejemplo n.º 18
0
/**
 * This is used by the client application program to get the next entry in the directory
 * @param  folder Pointer to the remote folder to close
 * @return        Pointer to the next entry in the directory
 */
struct fsDirent *fsReadDir(FSDIR *folder) {

	#ifdef _DEBUG_CLI_
	printf("in fsReadDir\n");
	#endif
	
	remote_folder_server *server = findServerByFolderName(folder->folderName);
	return_type ans = make_remote_call( server->srvIpOrDomName,
										server->srvPort ,
										"fsReadDir", 1,
										sizeof(int), (void *)(server->clientId));
	
	if (ans.return_size == 0) {
		return NULL;
	} else if (ans.return_size == sizeof(int)) {
		//set errno and return null
		errno = ans.return_size;
		return NULL;
	} else {
		//read entType and entName
		#ifdef _DEBUG_CLI_
			printf("return_size: %d\n", ans.return_size);
		#endif
	
		struct fsDirent *dir = (struct fsDirent *)malloc(sizeof(struct fsDirent));
		int *type = (int*)malloc(sizeof(int));
		memcpy( type, 
                ans.return_val, 
                sizeof(int));
		dir->entType = (unsigned char)(*type);
		char * index = (char*)(ans.return_val);
		index += sizeof(int);
		// printf("return_size: %d, size of unsigned char: %d\n", ans.return_size, sizeof(unsigned char));
		strcpy( dir->entName, (char*)index);
		return dir;
	}
}
Ejemplo n.º 19
0
/**
 * Mounts the remote server folder locally, and have it be referred to as local_folder_name.
 * Returns 0 on success, and −1 on failure.
 *
 * @param ip_or_domain      server IP address or domain name
 * @param port_no           server port no.
 * @param local_folder_name name of the mounted folder
 * @return                  0 on success, and −1 on failure
 */
int fsMount(const char *ip_or_domain, const unsigned int port_no, const char *local_folder_name) {
    struct mount_info *info = mount_info_list_find(local_folder_name, true);
    if (info != NULL) {
        errno = EBUSY;
        return -1;
    }

    return_type ans = make_remote_call(ip_or_domain, port_no, "fsMount", 1,
                                       strlen(local_folder_name), (void *) local_folder_name);
    fs_response *response = (fs_response *)ans.return_val;
    int retval = -1;
    if (!handle_possible_error(response)) {
        struct mount_info *info = (struct mount_info *) malloc(sizeof(struct mount_info));
        strcpy(info->ip_or_domain, ip_or_domain);
        strcpy(info->local_folder_name, local_folder_name);
        info->port_no = port_no;
        info->next = NULL;
        mount_info_list_insert(info);
        retval = 0;
    }

    free(response);
    return retval;
}
Ejemplo n.º 20
0
/**
 * This is used by the client application program to read from a remote file
 * @param  fd    File descriptor of the file to read from
 * @param  buf   Pointer to a buffer to hold the content of the read file
 * @param  count Size of the buffer to read
 * @return       Number of bytes actually read, -1 on error
 */
int fsRead(int fd, void *buf, const unsigned int count) {
	#ifdef _DEBUG_CLI_
	printf("in fsRead\n");
	#endif
	client_fd *clientFdNode = getNodeFromClientFd(fd);
	remote_folder_server *server = findServerByFolderName(clientFdNode->localFolderName);
	return_type ans = make_remote_call( server->srvIpOrDomName,
										server->srvPort,
										"fsRead", 2,
										sizeof(int), (void *)(&(clientFdNode->serverFd)),
										sizeof(unsigned int), (void *)(&count));
    
    int errorDescriptor;
	int returnedValue;

	if (ans.return_size == 0) {
		//error set errno
		#ifdef _DEBUG_CLI_
		printf("return_size zero: %d\n", ans.return_size);
		#endif
		errno = EBADMSG;
		return -1;
	} else if (ans.return_size == 2*sizeof(int)) {
		// there is an error
		memcpy(&errorDescriptor, ans.return_val, sizeof(int));
		memcpy(&returnedValue, ans.return_val+sizeof(int), sizeof(int));
		if (errorDescriptor == 0) {
			#ifdef _DEBUG_CLI_
			printf("return_size =  2*sizeof(int) but errorDescriptor = 0\n");
			#endif
			// errno = returnedValue;
			return -1;
		} else {
			#ifdef _DEBUG_CLI_
			printf("there is an error: %d\n", strerror(returnedValue));
			#endif
			errno = returnedValue;
			return -1;
		}
	} else if(ans.return_size > 2*sizeof(int)) {
		memcpy(&errorDescriptor, ans.return_val, sizeof(int));
		memcpy(&returnedValue, ans.return_val+sizeof(int), sizeof(int));
		if (errorDescriptor == 0) {
			memcpy(buf, ans.return_val+2*sizeof(int), returnedValue);
			return returnedValue;
		} else {
			errno = returnedValue;
			return -1;
		}
	} else {
		#ifdef _DEBUG_CLI_
		printf("Unrecognized return value from server\n");
		#endif
		return -1;
	}

	// if (errorDescriptor == -1) {
	// 	errno = returnedValue;
	// 	return -1;
	// }

	// return returnedValue;
}