Skip to content
Permalink
60ef72651f
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
executable file 1230 lines (1118 sloc) 33.5 KB
/*
* (C) 2001 Clemson University and The University of Chicago
*
* See COPYING in top-level directory.
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include <time.h>
#ifndef WIN32
#include <pwd.h>
#include <grp.h>
#endif
#include <assert.h>
#ifndef WIN32
#include <getopt.h>
#endif
#include "pvfs2.h"
#include "str-utils.h"
#include "pvfs2-internal.h"
#ifndef PVFS2_VERSION
#define PVFS2_VERSION "Unknown"
#endif
#ifdef WIN32
#define snprintf _snprintf
#endif
/* TODO: this can be larger after system interface readdir logic
* is in place to break up large readdirs into multiple operations
*/
/* MAX_NUM_DIRENTS cannot be any larger than PVFS_REQ_LIMIT_LISTATTR */
#define MAX_NUM_DIRENTS 60
/*
Define the maximum length of a single line of output. This is about the
size of 256 maximum path segments, a file name, and attributes.
*/
#define ENTRY_MAX 66560
/*
arbitrarily restrict the number of paths
that this ls version can take as arguments
*/
#define MAX_NUM_PATHS 8
/*
Max length of the fully formatted date/time fields
*/
#define MAX_TIME_LENGTH 128
/*
Length of the formatted date/time for --all-times option
*/
#define ALL_TIMES_LENGTH 25
/* optional parameters, filled in by parse_args() */
struct options
{
int list_human_readable;
int list_long;
int list_verbose;
int list_recursive;
int list_numeric_uid_gid;
int list_directory;
int list_no_group;
int list_almost_all;
int list_all;
int list_no_owner;
int list_inode;
int list_all_times;
int list_use_si_units;
char *start[MAX_NUM_PATHS];
int num_starts;
};
struct subdir_list
{
char *path;
struct subdir_list *next;
};
typedef struct subdir_list subdir;
static char *process_name = NULL;
static int do_timing = 0;
static struct options* parse_args(int argc, char* argv[]);
static void usage(int argc, char** argv);
static void print_entry(
char *entry_name,
PVFS_handle handle,
PVFS_fs_id fs_id,
PVFS_sys_attr *attr,
int attr_error,
struct options *opts,
char* entry_buffer);
static int do_list(
char *full_path,
char *start,
int fs_id,
struct options *opts,
char *entry_buffer);
static void print_entry_attr(
PVFS_handle handle,
char *entry_name,
PVFS_sys_attr *attr,
struct options *opts,
char *entry_buffer);
#define print_dot_and_dot_dot_info_if_required(refn) \
do { \
if (opts->list_all && !opts->list_almost_all) { \
/* \
we have to fake access to the .. handle \
since our sysint lookup doesn't return that \
kind of intermediate information. we can get \
this value, by manually resolving it with lookups \
on base dirs, but I'm not sure it's worth it \
*/ \
if (opts->list_inode && !opts->list_long) { \
printf("%llu .\n",llu(refn.handle)); \
printf("%llu .. (faked)\n",llu(refn.handle)); \
} \
else if (opts->list_long) { \
print_entry(".", refn.handle, \
refn.fs_id, NULL, 0, opts, \
entry_buffer); \
print_entry(".. (faked)", refn.handle, \
refn.fs_id, NULL, 0, opts, \
entry_buffer); \
} \
else { \
printf(".\n"); \
printf("..\n"); \
} \
} \
} while(0)
/*
build a string of a specified length that's either
left or right justified based on the src string;
caller must free ptr passed out as *out_str_p
*/
static inline void format_size_string(
char *src_str, int num_spaces_total, char **out_str_p,
int right_justified, int hard_limit)
{
int len = 0;
int spaces_size_allowed = 0;
char *buf = NULL, *start = NULL, *src_start = NULL;
assert(src_str);
len = strlen(src_str);
if (hard_limit)
{
spaces_size_allowed = (num_spaces_total ? num_spaces_total : len);
}
else
{
spaces_size_allowed = len;
if (len < num_spaces_total)
{
spaces_size_allowed = num_spaces_total;
}
}
buf = (char *)malloc(spaces_size_allowed+1);
assert(buf);
memset(buf,0,spaces_size_allowed+1);
if ((len > 0) && (len <= spaces_size_allowed))
{
memset(buf,' ',(spaces_size_allowed));
src_start = src_str;
if (right_justified)
{
start = &buf[(spaces_size_allowed-(len))];
}
else
{
start = buf;
}
while(src_start && (*src_start))
{
*start++ = *src_start++;
}
*out_str_p = strdup(buf);
}
else if (len > 0)
{
/* if the string is too long, don't format it */
*out_str_p = strdup(src_str);
}
else if (len == 0)
{
*out_str_p = strdup("");
}
free(buf);
}
void print_entry_attr(
PVFS_handle handle,
char *entry_name,
PVFS_sys_attr *attr,
struct options *opts,
char *entry_buffer)
{
char *formatted_size = NULL;
char *formatted_owner = NULL, *formatted_group = NULL, *formatted_time = NULL;
#ifdef WIN32
#else
struct group *grp = NULL;
struct passwd *pwd = NULL;
#endif
char *empty_str = "";
char *owner = empty_str, *group = empty_str;
char *inode = empty_str;
time_t mtime, atime, ctime;
struct tm *time;
PVFS_size size = 0;
char scratch_owner[16] = {0}, scratch_group[16] = {0}, scratch_time[MAX_TIME_LENGTH] = {0}, scratch_big_time[MAX_TIME_LENGTH] = {0};
char scratch_size[16] = {0}, scratch_inode[21] = {0};
char f_type = '-';
char group_x_char = '-';
int num_bytes = 0;
if (!opts->list_all && (entry_name[0] == '.'))
{
return;
}
if (attr == NULL)
{
return;
}
mtime = (time_t)attr->mtime;
time = localtime(&mtime);
if(opts->list_all_times)
{
atime = (time_t)attr->atime;
ctime = (time_t)attr->ctime;
#ifdef WIN32
num_bytes = strftime( scratch_time,ALL_TIMES_LENGTH+1,"%Y-%m-%d %H:%M:%S %z",time );
#else
num_bytes = strftime( scratch_time,ALL_TIMES_LENGTH+1,"%F %H:%M:%S %z",time );
#endif
strncpy(scratch_big_time,scratch_time,num_bytes);
time = localtime(&atime);
#ifdef WIN32
num_bytes = strftime( scratch_time,ALL_TIMES_LENGTH+3," %Y-%m-%d %H:%M:%S %z",time );
#else
num_bytes = strftime( scratch_time,ALL_TIMES_LENGTH+3," %F %H:%M:%S %z",time );
#endif
strncat(scratch_big_time,scratch_time,num_bytes);
time = localtime(&ctime);
#ifdef WIN32
num_bytes = strftime( scratch_time,ALL_TIMES_LENGTH+3," %Y-%m-%d %H:%M:%S %z",time );
#else
num_bytes = strftime( scratch_time,ALL_TIMES_LENGTH+3," %F %H:%M:%S %z",time );
#endif
strncat(scratch_big_time,scratch_time,num_bytes);
format_size_string(scratch_big_time,strlen(scratch_big_time),&formatted_time,0,1);
}
else
{
#ifdef WIN32
strftime( scratch_time,17,"%Y-%m-%d %H:%M",time );
#else
strftime( scratch_time,17,"%F %H:%M",time );
#endif
format_size_string(scratch_time,16,&formatted_time,0,1);
}
snprintf(scratch_owner,16,"%d",(int)attr->owner);
snprintf(scratch_group,16,"%d",(int)attr->group);
if (opts->list_inode)
{
snprintf(scratch_inode,21,"%llu ",llu(handle));
inode = scratch_inode;
}
if ((attr->objtype == PVFS_TYPE_METAFILE) &&
(attr->mask & PVFS_ATTR_SYS_SIZE))
{
size = attr->size;
}
else if ((attr->objtype == PVFS_TYPE_SYMLINK) &&
(attr->link_target))
{
size = (PVFS_size)strlen(attr->link_target);
}
else if (attr->objtype == PVFS_TYPE_DIRECTORY)
{
size = (PVFS_size)4096;
}
if (opts->list_human_readable)
{
PVFS_util_make_size_human_readable(
size,scratch_size,16,opts->list_use_si_units);
}
else
{
snprintf(scratch_size,16, "%lld", lld(size));
}
format_size_string(scratch_size,11,&formatted_size,1,1);
if (!opts->list_no_owner)
{
owner = scratch_owner;
}
if (!opts->list_no_group)
{
group = scratch_group;
}
if (!opts->list_numeric_uid_gid)
{
if (!opts->list_no_owner)
{
#ifdef WIN32
owner = scratch_owner;
#else
pwd = getpwuid((uid_t)attr->owner);
owner = (pwd ? pwd->pw_name : scratch_owner);
#endif
}
if (!opts->list_no_group)
{
#ifdef WIN32
group = scratch_group;
#else
grp = getgrgid((gid_t)attr->group);
group = (grp ? grp->gr_name : scratch_group);
#endif
}
}
/* for owner and group allow the fields to grow larger than 8 if
* necessary (set hard_limit to 0), but pad anything smaller to
* take up 8 spaces.
*/
format_size_string(owner,8,&formatted_owner,0,0);
format_size_string(group,8,&formatted_group,0,0);
if (attr->objtype == PVFS_TYPE_DIRECTORY)
{
f_type = 'd';
}
else if (attr->objtype == PVFS_TYPE_SYMLINK)
{
f_type = 'l';
}
/* special case to set setgid display for groups if needed */
if(attr->perms & PVFS_G_SGID)
{
group_x_char = ((attr->perms & PVFS_G_EXECUTE) ? 's' : 'S');
}
else
{
group_x_char = ((attr->perms & PVFS_G_EXECUTE) ? 'x' : '-');
}
snprintf(entry_buffer,ENTRY_MAX,"%s %c%c%c%c%c%c%c%c%c%c 1 %s %s %s "
"%s %s",
inode,
f_type,
((attr->perms & PVFS_U_READ) ? 'r' : '-'),
((attr->perms & PVFS_U_WRITE) ? 'w' : '-'),
((attr->perms & PVFS_U_EXECUTE) ? 'x' : '-'),
((attr->perms & PVFS_G_READ) ? 'r' : '-'),
((attr->perms & PVFS_G_WRITE) ? 'w' : '-'),
group_x_char,
((attr->perms & PVFS_O_READ) ? 'r' : '-'),
((attr->perms & PVFS_O_WRITE) ? 'w' : '-'),
((attr->perms & PVFS_O_EXECUTE) ? 'x' : '-'),
formatted_owner,
formatted_group,
formatted_size,
formatted_time,
entry_name);
if (formatted_size)
{
free(formatted_size);
}
if (formatted_owner)
{
free(formatted_owner);
}
if (formatted_group)
{
free(formatted_group);
}
if (formatted_time)
{
free(formatted_time);
}
if (attr->objtype == PVFS_TYPE_SYMLINK)
{
assert(attr->link_target);
if (opts->list_long)
{
printf("%s -> %s\n", entry_buffer, attr->link_target);
}
else
{
printf("%s\n",entry_buffer);
}
}
else
{
printf("%s\n",entry_buffer);
}
}
void print_entry(
char *entry_name,
PVFS_handle handle,
PVFS_fs_id fs_id,
PVFS_sys_attr *attr,
int attr_error,
struct options *opts,
char *entry_buffer)
{
int ret = -1;
PVFS_object_ref ref;
PVFS_credentials credentials;
PVFS_sysresp_getattr getattr_response;
if (!opts->list_long)
{
if (opts->list_inode)
{
printf("%llu %s\n", llu(handle), entry_name);
}
else
{
printf("%s\n", entry_name);
}
return;
}
if (attr_error == 0)
{
if(!attr)
{
/* missing attributes (possibly for . or .. entries); get them
* the old fashioned way
*/
ref.handle = handle;
ref.fs_id = fs_id;
memset(&getattr_response,0, sizeof(PVFS_sysresp_getattr));
PVFS_util_gen_credentials(&credentials);
ret = PVFS_sys_getattr(ref, PVFS_ATTR_SYS_ALL_NOHINT,
&credentials, &getattr_response, NULL);
if (ret)
{
fprintf(stderr,"Failed to get attributes on handle %llu,%d\n",
llu(handle),fs_id);
PVFS_perror("Getattr failure", ret);
return;
}
print_entry_attr(handle, entry_name, &getattr_response.attr, opts, entry_buffer);
}
else
{
print_entry_attr(handle, entry_name, attr, opts, entry_buffer);
}
}
}
static double Wtime(void)
{
struct timeval t;
gettimeofday(&t, NULL);
return((double)t.tv_sec * 1e03 + (double)(t.tv_usec) * 1e-03);
}
int do_list(
char *full_path,
char *start,
int fs_id,
struct options *opts,
char *entry_buffer)
{
int i = 0, printed_dot_info = 0;
int ret = -1;
int pvfs_dirent_incount;
char *name = NULL, *cur_file = NULL;
PVFS_handle cur_handle;
PVFS_sysresp_lookup lk_response;
PVFS_sysresp_readdirplus rdplus_response;
PVFS_sysresp_getattr getattr_response;
PVFS_credentials credentials;
PVFS_object_ref ref;
PVFS_ds_position token;
uint64_t dir_version = 0;
double begin = 0., end;
subdir *current, *head = NULL, *tail = NULL;
name = start;
memset(&lk_response,0,sizeof(PVFS_sysresp_lookup));
PVFS_util_gen_credentials(&credentials);
if (opts->list_recursive || opts->num_starts > 1)
{
printf("%s%s:\n",full_path,start);
}
ret = PVFS_sys_lookup(fs_id, name, &credentials,
&lk_response, PVFS2_LOOKUP_LINK_NO_FOLLOW, NULL);
if(ret < 0)
{
PVFS_perror("PVFS_sys_lookup", ret);
return -1;
}
ref.handle = lk_response.ref.handle;
ref.fs_id = fs_id;
pvfs_dirent_incount = MAX_NUM_DIRENTS;
memset(&getattr_response,0,sizeof(PVFS_sysresp_getattr));
if (PVFS_sys_getattr(ref, PVFS_ATTR_SYS_ALL,
&credentials, &getattr_response, NULL) == 0)
{
if ((getattr_response.attr.objtype == PVFS_TYPE_METAFILE) ||
(getattr_response.attr.objtype == PVFS_TYPE_SYMLINK) ||
((getattr_response.attr.objtype == PVFS_TYPE_DIRECTORY) &&
(opts->list_directory)))
{
char segment[128] = {0};
PVFS_sysresp_getparent getparent_resp;
PINT_remove_base_dir(name, segment, 128);
if (strcmp(segment,"") == 0)
{
snprintf(segment,128,"/");
}
if (getattr_response.attr.objtype == PVFS_TYPE_DIRECTORY)
{
if (PVFS_sys_getparent(ref.fs_id, name, &credentials,
&getparent_resp, NULL) == 0)
{
print_dot_and_dot_dot_info_if_required(
getparent_resp.parent_ref);
}
}
if (opts->list_long)
{
print_entry_attr(ref.handle, segment,
&getattr_response.attr, opts, entry_buffer);
}
else
{
print_entry(segment, ref.handle, ref.fs_id,
NULL,
0,
opts, entry_buffer);
}
return 0;
}
}
if (do_timing)
begin = Wtime();
token = 0;
do
{
memset(&rdplus_response, 0, sizeof(PVFS_sysresp_readdirplus));
ret = PVFS_sys_readdirplus(
ref, (!token ? PVFS_READDIR_START : token),
pvfs_dirent_incount, &credentials,
(opts->list_long) ?
PVFS_ATTR_SYS_ALL : PVFS_ATTR_SYS_ALL_NOSIZE,
&rdplus_response,
NULL);
if(ret < 0)
{
PVFS_perror("PVFS_sys_readdir", ret);
return -1;
}
if (dir_version == 0)
{
dir_version = rdplus_response.directory_version;
}
else if (opts->list_verbose)
{
if (dir_version != rdplus_response.directory_version)
{
fprintf(stderr, "*** directory changed! listing may "
"not be correct\n");
dir_version = rdplus_response.directory_version;
}
}
if (!printed_dot_info)
{
/*
the list_all option prints files starting with .;
the almost_all option skips the '.', '..' printing
*/
print_dot_and_dot_dot_info_if_required(ref);
printed_dot_info = 1;
}
for(i = 0; i < rdplus_response.pvfs_dirent_outcount; i++)
{
PVFS_sys_attr *attr;
cur_file = rdplus_response.dirent_array[i].d_name;
cur_handle = rdplus_response.dirent_array[i].handle;
print_entry(cur_file, cur_handle, fs_id,
&rdplus_response.attr_array[i],
rdplus_response.stat_err_array[i],
opts, entry_buffer);
attr = &rdplus_response.attr_array[i];
if(attr->objtype == PVFS_TYPE_DIRECTORY && opts->list_recursive)
{
int path_len = strlen(start) + strlen(cur_file) + 1;
current = (subdir *) malloc(sizeof(subdir));
/* Prevent duplicate slashes in path */
if(start[strlen(start)-1] == '/')
{
current->path = (char *) malloc(path_len);
snprintf(current->path,path_len,"%s%s",start,cur_file);
}
else
{
current->path = (char *) malloc(path_len + 1);
snprintf(current->path,path_len+1,"%s/%s",start,cur_file);
}
/* Update linked list of subdirectories to recurse */
current->next = NULL;
if(!head)
{
head = current;
tail = current;
}
else
{
tail->next = current;
tail = current;
}
}
}
token = rdplus_response.token;
if (rdplus_response.pvfs_dirent_outcount)
{
free(rdplus_response.dirent_array);
rdplus_response.dirent_array = NULL;
free(rdplus_response.stat_err_array);
rdplus_response.stat_err_array = NULL;
for (i = 0; i < rdplus_response.pvfs_dirent_outcount; i++) {
if (rdplus_response.attr_array)
{
PVFS_util_release_sys_attr(&rdplus_response.attr_array[i]);
}
}
free(rdplus_response.attr_array);
rdplus_response.attr_array = NULL;
}
} while(rdplus_response.pvfs_dirent_outcount == pvfs_dirent_incount);
if (do_timing) {
end = Wtime();
printf("PVFS_sys_readdirplus took %g msecs\n",
(end - begin));
}
if (rdplus_response.pvfs_dirent_outcount)
{
free(rdplus_response.dirent_array);
rdplus_response.dirent_array = NULL;
free(rdplus_response.stat_err_array);
rdplus_response.stat_err_array = NULL;
for (i = 0; i < rdplus_response.pvfs_dirent_outcount; i++) {
if (rdplus_response.attr_array)
{
PVFS_util_release_sys_attr(&rdplus_response.attr_array[i]);
}
}
free(rdplus_response.attr_array);
rdplus_response.attr_array = NULL;
}
if (opts->list_recursive)
{
current = head;
while(current)
{
printf("\n");
do_list(full_path,current->path,fs_id,opts,entry_buffer);
current = current->next;
free(head->path);
free(head);
head = current;
}
}
return 0;
}
/* parse_args()
*
* parses command line arguments
*
* returns pointer to options structure on success, NULL on failure
*/
#ifdef WIN32
static struct options* parse_args(int argc, char* argv[])
{
int i = 0, ret = 0, option_index = 0;
const char *cur_option = NULL;
struct options* tmp_opts = NULL;
static char str_opts[14][16] = {
"help",
"human-readable",
"si",
"version",
"recursive",
"verbose",
"numeric-uid-gid",
"directory",
"no-group",
"almost-all",
"all",
"inode",
"size",
"all-times"
};
tmp_opts = (struct options*)malloc(sizeof(struct options));
if (!tmp_opts)
{
return(NULL);
}
memset(tmp_opts, 0, sizeof(struct options));
/* RVndGoAaiglt */
option_index = 1;
while ((option_index < argc) && (argv[option_index][0] == '-'))
{
cur_option = argv[option_index];
if ((strcmp(cur_option, "-?") == 0) ||
(strcmp(cur_option, "--help") == 0))
{
usage(argc, argv);
exit(0);
}
else if ((strcmp(cur_option, "--human-readable") == 0) ||
(strcmp(cur_option, "-h") == 0))
{
tmp_opts->list_human_readable = 1;
}
else if (strcmp(cur_option, "--si") == 0)
{
tmp_opts->list_use_si_units = 1;
}
else if (strcmp(cur_option, "--version") == 0)
{
printf("%s\n", PVFS2_VERSION);
exit(0);
}
else if ((strcmp(cur_option, "--recursive") == 0) ||
(strcmp(cur_option, "-R") == 0))
{
tmp_opts->list_recursive = 1;
}
else if ((strcmp(cur_option, "--verbose") == 0) ||
(strcmp(cur_option, "-V") == 0))
{
tmp_opts->list_verbose = 1;
}
else if ((strcmp(cur_option, "--numeric-uid-gid") == 0) ||
(strcmp(cur_option, "-n") == 0))
{
tmp_opts->list_long = 1;
tmp_opts->list_numeric_uid_gid = 1;
}
else if ((strcmp(cur_option, "--directory") == 0) ||
(strcmp(cur_option, "-d") == 0))
{
tmp_opts->list_directory = 1;
}
else if ((strcmp(cur_option, "--no-group") == 0) ||
(strcmp(cur_option, "-G") == 0))
{
tmp_opts->list_long = 1;
tmp_opts->list_no_group = 1;
}
else if ((strcmp(cur_option, "--almost-all") == 0) ||
(strcmp(cur_option, "-A") == 0))
{
tmp_opts->list_almost_all = 1;
}
else if ((strcmp(cur_option, "--all") == 0) ||
(strcmp(cur_option, "-a") == 0))
{
tmp_opts->list_all = 1;
}
else if ((strcmp(cur_option, "--inode") == 0) ||
(strcmp(cur_option, "-i") == 0))
{
tmp_opts->list_inode = 1;
}
else if ((strcmp(cur_option, "--all-times") == 0))
{
tmp_opts->list_all_times = 1;
}
else if (strcmp(cur_option, "-l") == 0)
{
tmp_opts->list_long = 1;
}
else
{
usage(argc, argv);
exit(EXIT_FAILURE);
}
option_index++;
}
for(i = option_index; i < argc; i++)
{
if (tmp_opts->num_starts < MAX_NUM_PATHS)
{
tmp_opts->start[i-option_index] = argv[i];
tmp_opts->num_starts++;
}
else
{
fprintf(stderr,"Ignoring path %s\n",argv[i]);
}
}
return tmp_opts;
}
#else
static struct options* parse_args(int argc, char* argv[])
{
int i = 0, ret = 0, option_index = 0;
const char *cur_option = NULL;
struct options* tmp_opts = NULL;
static struct option long_opts[] =
{
{"help",0,0,0},
{"human-readable",0,0,0},
{"si",0,0,0},
{"version",0,0,0},
{"recursive",0,0,0},
{"verbose",0,0,0},
{"numeric-uid-gid",0,0,0},
{"directory",0,0,0},
{"no-group",0,0,0},
{"almost-all",0,0,0},
{"all",0,0,0},
{"inode",0,0,0},
{"size",0,0,0},
{"all-times",0,0,0},
{0,0,0,0}
};
tmp_opts = (struct options*)malloc(sizeof(struct options));
if (!tmp_opts)
{
return(NULL);
}
memset(tmp_opts, 0, sizeof(struct options));
while((ret = getopt_long(argc, argv, "hRVndGoAaiglt",
long_opts, &option_index)) != -1)
{
switch(ret)
{
case 0:
cur_option = long_opts[option_index].name;
if (strcmp("help", cur_option) == 0)
{
usage(argc, argv);
exit(0);
}
else if (strcmp("human-readable", cur_option) == 0)
{
goto list_human_readable;
}
else if (strcmp("si", cur_option) == 0)
{
tmp_opts->list_use_si_units = 1;
break;
}
else if (strcmp("version", cur_option) == 0)
{
printf("%s\n", PVFS2_VERSION);
exit(0);
}
else if (strcmp("recursive", cur_option) == 0)
{
goto list_recursive;
}
else if (strcmp("verbose", cur_option) == 0)
{
goto list_verbose;
}
else if (strcmp("numeric-uid-gid", cur_option) == 0)
{
goto list_numeric_uid_gid;
}
else if (strcmp("directory", cur_option) == 0)
{
goto list_directory;
}
else if (strcmp("no-group", cur_option) == 0)
{
goto list_no_group;
}
else if (strcmp("almost-all", cur_option) == 0)
{
goto list_almost_all;
}
else if (strcmp("all", cur_option) == 0)
{
goto list_all;
}
else if (strcmp("inode", cur_option) == 0)
{
goto list_inode;
}
else if (strcmp("all-times", cur_option) == 0)
{
goto list_all_times;
}
else
{
usage(argc, argv);
exit(EXIT_FAILURE);
}
break;
case 'h':
list_human_readable:
tmp_opts->list_human_readable = 1;
break;
case 'R':
list_recursive:
tmp_opts->list_recursive = 1;
break;
case 'V':
list_verbose:
tmp_opts->list_verbose = 1;
break;
case 'l':
tmp_opts->list_long = 1;
break;
case 'n':
list_numeric_uid_gid:
tmp_opts->list_long = 1;
tmp_opts->list_numeric_uid_gid = 1;
break;
case 'd':
list_directory:
tmp_opts->list_directory = 1;
break;
case 'o':
list_no_group:
tmp_opts->list_long = 1;
tmp_opts->list_no_group = 1;
break;
case 'A':
list_almost_all:
tmp_opts->list_almost_all = 1;
break;
case 'a':
list_all:
tmp_opts->list_all = 1;
break;
case 'g':
tmp_opts->list_long = 1;
tmp_opts->list_no_owner = 1;
break;
case 'i':
list_inode:
tmp_opts->list_inode = 1;
break;
list_all_times:
tmp_opts->list_all_times = 1;
break;
case 't':
do_timing = 1;
break;
case '?':
usage(argc, argv);
exit(EXIT_FAILURE);
}
}
for(i = optind; i < argc; i++)
{
if (tmp_opts->num_starts < MAX_NUM_PATHS)
{
tmp_opts->start[i-optind] = argv[i];
tmp_opts->num_starts++;
}
else
{
fprintf(stderr,"Ignoring path %s\n",argv[i]);
}
}
return tmp_opts;
}
#endif
static void usage(int argc, char** argv)
{
fprintf(stderr, "Usage: %s [OPTION]... [FILE]...\n", argv[0]);
fprintf(stderr, "List information about the FILEs (the current "
"directory by default)\n\n");
fprintf(stderr," -a, --all "
"do not hide entries starting with .\n");
fprintf(stderr," -A, --almost-all do not list "
"implied . and ..\n");
fprintf(stderr," -d, --directory list directory "
"entries instead of contents\n");
fprintf(stderr," -g like -l, but do "
"not list owner\n");
fprintf(stderr," -G, --no-group inhibit display "
"of group information\n");
fprintf(stderr," -h, --human-readable print sizes in human "
"readable format\n\t\t\t\t(e.g. 1K 234M 2G)\n");
fprintf(stderr," --si likewise, but use powers "
"of 1000, not 1024\n");
fprintf(stderr," -i, --inode print index number "
"of each file\n");
fprintf(stderr," -l use a long listing "
"format\n");
fprintf(stderr," -n, --numeric-uid-gid like -l, but list "
"numeric UIDs and GIDs\n");
fprintf(stderr," --all-times display atime, mtime,"
" and ctime information\n");
fprintf(stderr," -o like -l, but do not "
"list group information\n");
fprintf(stderr," --help display this help "
"and exit\n");
fprintf(stderr," -R, --recursive list subdirectories "
"recursively\n");
fprintf(stderr," -V, --verbose reports if the dir is "
"changing during listing\n");
fprintf(stderr," --version output version "
"information and exit\n");
return;
}
int main(int argc, char **argv)
{
int ret = -1, i = 0;
char pvfs_path[MAX_NUM_PATHS][PVFS_NAME_MAX];
PVFS_fs_id fs_id_array[MAX_NUM_PATHS] = {0};
const PVFS_util_tab* tab;
struct options* user_opts = NULL;
char current_dir[PVFS_NAME_MAX] = {0};
int found_one = 0;
char *entry_buffer = malloc(ENTRY_MAX);
process_name = argv[0];
user_opts = parse_args(argc, argv);
if (!user_opts)
{
fprintf(stderr, "Error: failed to parse command line "
"arguments.\n");
usage(argc, argv);
return(-1);
}
tab = PVFS_util_parse_pvfstab(NULL);
if (!tab)
{
fprintf(stderr, "Error: failed to parse pvfstab.\n");
return(-1);
}
for(i = 0; i < MAX_NUM_PATHS; i++)
{
memset(pvfs_path[i],0,PVFS_NAME_MAX);
}
ret = PVFS_sys_initialize(GOSSIP_NO_DEBUG);
if (ret < 0)
{
PVFS_perror("PVFS_sys_initialize", ret);
return(-1);
}
/* initialize each file system that we found in the tab file */
for(i = 0; i < tab->mntent_count; i++)
{
ret = PVFS_sys_fs_add(&tab->mntent_array[i]);
if (ret == 0)
{
found_one = 1;
}
}
if (!found_one)
{
fprintf(stderr, "Error: could not initialize any file systems "
"from %s\n", tab->tabfile_name);
PVFS_sys_finalize();
return(-1);
}
if (user_opts->num_starts == 0)
{
snprintf(current_dir,PVFS_NAME_MAX,"%s/",
tab->mntent_array[0].mnt_dir);
user_opts->start[0] = current_dir;
user_opts->num_starts = 1;
}
for(i = 0; i < user_opts->num_starts; i++)
{
ret = PVFS_util_resolve(user_opts->start[i],
&fs_id_array[i], pvfs_path[i], PVFS_NAME_MAX);
if ((ret == 0) && (pvfs_path[i][0] == '\0'))
{
strcpy(pvfs_path[i], "/");
}
if (ret < 0)
{
fprintf(stderr, "Error: could not find file system "
"for %s in pvfstab\n", user_opts->start[i]);
return(-1);
}
}
for(i = 0; i < user_opts->num_starts; i++)
{
char *substr = strstr(user_opts->start[i],pvfs_path[i]);
char *index = user_opts->start[i];
char *search = substr;
int j = 0;
/* Keep the mount path info to mimic /bin/ls output */
if( strncmp(pvfs_path[i],"/",strlen(pvfs_path[i])) )
{
/* Get last matching substring */
while (search)
{
substr = search;
search = strstr(++search,pvfs_path[i]);
}
}
else /* Root directory case has nothing to match */
{
substr = &user_opts->start[i][strlen(user_opts->start[i])];
}
while ((index != substr) && (substr != NULL))
{
index++;
j++;
}
user_opts->start[i][++j] = '\0';
do_list(user_opts->start[i], pvfs_path[i], fs_id_array[i], user_opts, entry_buffer);
if (user_opts->num_starts > 1)
{
printf("\n");
}
}
PVFS_sys_finalize();
free(user_opts);
free(entry_buffer);
return(ret);
}
/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
* End:
*
* vim: ts=8 sts=4 sw=4 expandtab
*/