hdfs_connect_as_user.c
This application demonstrates how to create and write to files impersonating another user by
          using the API hdfsConnectAsUser().
Before running this application, ensure that you have access to a cluster running Data Fabric file system.
To build and run it, download it from this page and copy it to a Data Fabric client or to a system with the mapr-core package
          installed. Then, modify the run.sh script in Building and Running C Applications on file system
            Clients to point to this sample application. Run the script and then run the
          application.
The application includes these header files:
- 
            
stdio.h - 
            
hdfs.h - 
            
stdlib.h - 
            
string.h 
hdfs.h.The application performs the actions that are described in the following sections.
- Takes two usernames and a hostname as input
 After compiling the application, type the following command to launch the application and pass in the two usernames (to impersonate) and host name:
hdfs_connect_as_user <username1> <username2> <hostname>if (argc < 4) { fprintf (stderr, "Provide two usernames to impersonate and the host name\n"); printf ("USAGE: ./hdfs_connect_as_user mapruser1 mapruser2 10.10.xx.xxx\n"); exit(EXIT_FAILURE); }- Stores the values of the arguments
 The application stores the values of the arguments in character arrays. The application uses the port, 7222, to connect to the given host, and uses character arrays for user directory and file path.
char *impersonate_user1 = argv[1]; char *impersonate_user2 = argv[2]; char *host_addr = argv[3]; int port_num = 7222; char user1_dir[100]; char writePath[100]; int ret_val;- Populates the directory path and file path
 The application creates a default path for the user directory and file.
sprintf(user1_dir, "/tmp/%s_dir", impersonate_user1); sprintf(writePath, "%s/test_file", user1_dir);- Sets an RPC timeout
 The
hdfsSetRpcTimeout()is specific to the libMapRClient version oflibhdfsand takes a value that is specified in seconds. The default is 99 seconds. If you change this value, set it either to 0 (which eliminates timeouts) or to a value greater than 30.int err = hdfsSetRpcTimeout(30); if (err) { fprintf(stderr, "Failed to set rpc timeout!\n"); exit(-1); }- Connects to the file system as the impersonated user
 The application connects to the file system as the impersonated user (<username1>) using
hdfsConnectAsUser(). If successful, this operation returns a handle to the file system.printf("Impersonate user: %s\n", impersonate_user1); printf("Connecting using hdfsConnectAsUser() as user %s\n", impersonate_user1); hdfsFS fs_handle = hdfsConnectAsUser(host_addr, port_num, impersonate_user1); if (fs_handle == NULL) { printf("hdfsConnectAsUser() failed.\n"); exit(EXIT_FAILURE); }- Creates a directory as the impersonated user
 The application creates a directory under
/tmpas the impersonated user (<username1>).printf("User1: Create a directory : %s\n", user1_dir); ret_val = hdfsCreateDirectory(fs_handle, user1_dir); if (ret_val != EXIT_SUCCESS) { printf("hdfsCreateDirectory() failed.\n"); exit(EXIT_FAILURE); }- Creates and opens a file
 - The application creates a file and opens the file, passing the following values to the
hdfsOpenFile()function:- The handle to the file system.
 - A flag to indicate the mode in which to open the file. In this case, the flag is
                  
O_WRONLY|O_CREAT. This flag creates the file and opens it for writing. 
For more details, see
hdfsOpenFile()documentation.printf("User1: Create and write to the file as user1 : %s\n", writePath); hdfsFile writeFile = hdfsOpenFile(fs_handle, writePath, O_WRONLY|O_CREAT, 0, 0, 0); if(!writeFile) { printf("hdfsOpenFile() failed.\n"); exit(EXIT_FAILURE); } - Writes to the open file
 The application writes to the open file as the impersonated user (<username1>).
char* buffer = "Hello, from user 1!"; tSize num_written_bytes = hdfsWrite(fs_handle, writeFile, (void*)buffer, strlen(buffer)+1); if (hdfsFlush(fs_handle, writeFile)) { printf("failed to flush %s\n", writePath); exit(EXIT_FAILURE); }- Closes the file
 The application closes the file after successfully writing to the file as the impersonated user (<username1>).
printf("User1: Close file %s.\n", writePath); hdfsCloseFile(fs_handle, writeFile);- Connects to the file system as the impersonating user
 The application connects to the file system as the second user (<username2>) using
hdfsConnectAsUser()and returns a handle to the file system.printf("Impersonate user: %s\n", impersonate_user2); printf("Connecting using hdfsConnectAsUser() as user %s\n", impersonate_user2); hdfsFS fs_handle2 = hdfsConnectAsUser(host_addr, port_num, impersonate_user2); if (fs_handle2 == NULL) { printf("hdfsConnectAsUser() failed.\n"); exit(EXIT_FAILURE); }- Tries to write to the file as the impersonating user
 The application tries to open the file created by the impersonated user (<username1>) and write to the file as the impersonating user (<username2>). This operation fails as the impersonating user (<username2>) is denied access to the file created by the impersonated user (<username1>) and the application returns error EACCES.
printf("User2: Try opening file created by user1 for writing : %s\n", writePath); hdfsFile writeFile2 = hdfsOpenFile(fs_handle2, writePath, O_WRONLY, 0, 0, 0); int errNum = errno; if(writeFile2) { printf("User2: hdfsOpenFile() should have failed for %s.\n", impersonate_user2); exit(EXIT_FAILURE); } else { if (errNum == EACCES) { printf("User2: As expected hdfsOpenFile() with EACCES.\n"); } else { printf("User2: hdfsOpenFile() failed with errno:%d expected %d.\n", errNum, EACCES); exit(EXIT_FAILURE); } }- Deletes a directory
 The application deletes a directory as the impersonated user (<username1>) using the file system handle created for this user.
printf("Delete directory : %s\n", user1_dir); ret_val = hdfsDelete(fs_handle, user1_dir, 1); if (ret_val != EXIT_SUCCESS) { printf("hdfsDelete() failed.\n"); exit(EXIT_FAILURE); }- Disconnects the impersonating user
 The application disconnect the impersonating user (<username2>) from the file system.
printf("Disconnect the impersonation user2.\n"); ret_val = hdfsDisconnect(fs_handle2); if (ret_val != EXIT_SUCCESS) { printf("hdfsDisconnect() failed.\n"); exit(EXIT_FAILURE); }- Disconnects the impersonated user
 The application disconnect the impersonated user (<username1>) from the file system.
printf("Disconnect the impersonation user1.\n"); ret_val = hdfsDisconnect(fs_handle); if (ret_val != EXIT_SUCCESS) { printf("hdfsDisconnect() failed.\n"); exit(EXIT_FAILURE); }
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hdfs.h" 
int main(int argc, char *argv[]) {
    if (argc < 4) {
	fprintf (stderr, "Provide two usernames to impersonate and the host name\n");
	printf ("USAGE: ./connectAsUser mapruser1 mapruser2 10.10.xx.xxx\n");
	exit(EXIT_FAILURE);
    }
    char *impersonate_user1 = argv[1];
    char *impersonate_user2 = argv[2];
    char *host_addr = argv[3];
    int port_num = 7222;
    char user1_dir[100];
    char writePath[100];
    int ret_val;
    /* Populate the directory patha nd file path */
    sprintf(user1_dir, "/tmp/%s_dir", impersonate_user1);
    sprintf(writePath, "%s/test_file", user1_dir);
    /* Impersonate as user1 using hdfsConnectAsUser(). */
    printf("Impersonate user: %s\n", impersonate_user1);
    printf("Connecting using hdfsConnectAsUser() as user %s\n", impersonate_user1);
    hdfsFS fs_handle = hdfsConnectAsUser(host_addr, port_num, impersonate_user1);
    if (fs_handle == NULL) {
        printf("hdfsConnectAsUser() failed.\n");
	exit(EXIT_FAILURE);
    }
    /* Create a directory under /tmp. This is done as the impersonated user1. */
    printf("User1: Create a directory : %s\n", user1_dir);
    ret_val = hdfsCreateDirectory(fs_handle, user1_dir);
    if (ret_val != EXIT_SUCCESS) {
        printf("hdfsCreateDirectory() failed.\n");
        exit(EXIT_FAILURE);
    }
    /* 
     * Create and write a file using the filesystem
     * handle from impersonate_user1.
     */
    printf("User1: Create and write to the file as user1 : %s\n", writePath);
    hdfsFile writeFile = hdfsOpenFile(fs_handle, writePath, O_WRONLY|O_CREAT, 0, 0, 0);
    if(!writeFile) {
        printf("hdfsOpenFile() failed.\n");
        exit(EXIT_FAILURE);
    }
   
    char* buffer = "Hello, from user 1!";
    tSize num_written_bytes = hdfsWrite(fs_handle, writeFile, (void*)buffer, strlen(buffer)+1);
    if (hdfsFlush(fs_handle, writeFile)) {
	printf("failed to flush %s\n", writePath);
	exit(EXIT_FAILURE);
    }
    printf("User1: Close file %s.\n", writePath);
    hdfsCloseFile(fs_handle, writeFile);
    /*
     * Impersonate as user 2 and try to write the file create by user1.
     * Writing to the file created by user1 will be denied with error EACCES.
     */ 
    printf("Impersonate user: %s\n", impersonate_user2);
    printf("Connecting using hdfsConnectAsUser() as user %s\n", impersonate_user2);
    hdfsFS fs_handle2 = hdfsConnectAsUser(host_addr, port_num, impersonate_user2);
    if (fs_handle2 == NULL) {
        printf("hdfsConnectAsUser() failed.\n");
        exit(EXIT_FAILURE);
    } 
   
    printf("User2: Try opening file created by user1 for writing : %s\n", writePath); 
    hdfsFile writeFile2 = hdfsOpenFile(fs_handle2, writePath, O_WRONLY, 0, 0, 0);
    int errNum = errno; 
    if(writeFile2) {
        printf("User2: hdfsOpenFile() should have failed for %s.\n", impersonate_user2);
        exit(EXIT_FAILURE);
    } else {
	if (errNum == EACCES) {
		printf("User2: As expected hdfsOpenFile() with EACCES.\n"); 
	} else {
		printf("User2: hdfsOpenFile() failed with errno:%d expected %d.\n", errNum, EACCES);
		exit(EXIT_FAILURE);
	}
   }
    /* Delete the directory. This is done using the fliesystem handle creatd for user1. */
    printf("Delete directory : %s\n", user1_dir);
    ret_val = hdfsDelete(fs_handle, user1_dir, 1);
    if (ret_val != EXIT_SUCCESS) {
	printf("hdfsDelete() failed.\n");
	exit(EXIT_FAILURE);
    }	
    /* Disconnect the impersonation user1 */ 
    printf("Disconnect the impersonation user1.\n");
    ret_val = hdfsDisconnect(fs_handle);
    if (ret_val != EXIT_SUCCESS) {
	printf("hdfsDisconnect() failed.\n");
	exit(EXIT_FAILURE);
    }
    /* Disconnect the impersonation user2 */
    printf("Disconnect the impersonation user2.\n");
    ret_val = hdfsDisconnect(fs_handle2);
    if (ret_val != EXIT_SUCCESS) {
        printf("hdfsDisconnect() failed.\n");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}