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 oflibhdfs
and 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
/tmp
as 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);
}