1 |
|
|
/** |
2 |
|
|
* This file is part of the CernVM File System. |
3 |
|
|
* |
4 |
|
|
* This is a simple test program to test the facilities of the libcvmfs C |
5 |
|
|
* (not C++) library, which is used by Parrot and some other tools. |
6 |
|
|
* |
7 |
|
|
* The goal here is not so much to build the ultimate testing tool, but to |
8 |
|
|
* provide a simple build target which can verify that libcvmfs is exporting the |
9 |
|
|
* proper set of symbols to be used by a C program. |
10 |
|
|
*/ |
11 |
|
|
|
12 |
|
|
#define __STDC_FORMAT_MACROS |
13 |
|
|
|
14 |
|
|
#include "cvmfs_config.h" |
15 |
|
|
|
16 |
|
|
#include <errno.h> |
17 |
|
|
#include <inttypes.h> |
18 |
|
|
|
19 |
|
|
#include <cassert> |
20 |
|
|
#include <cstdio> |
21 |
|
|
#include <cstdlib> |
22 |
|
|
#include <cstring> |
23 |
|
|
#include <ctime> |
24 |
|
|
#include <map> |
25 |
|
|
#include <string> |
26 |
|
|
|
27 |
|
|
#include "libcvmfs.h" |
28 |
|
|
|
29 |
|
|
#define TEST_LINE_MAX 1024 |
30 |
|
|
|
31 |
|
|
typedef std::map<std::string, cvmfs_context*> RepoMap; |
32 |
|
|
static RepoMap attached_repos; |
33 |
|
|
cvmfs_option_map *cvmfs_opts = NULL; |
34 |
|
|
|
35 |
|
|
void cvmfs_test_help() |
36 |
|
|
{ |
37 |
|
|
printf("commands are:\n"); |
38 |
|
|
printf(" attach <repo name (without .cern.ch)>\n"); |
39 |
|
|
printf(" detach <repo name (without .cern.ch)>\n"); |
40 |
|
|
printf(" list <path>\n"); |
41 |
|
|
printf(" cat <path>\n"); |
42 |
|
|
printf(" quit\n"); |
43 |
|
|
} |
44 |
|
|
|
45 |
|
|
static void cvmfs_log_ignore(const char *msg) { |
46 |
|
|
// Remove comment to debug test failures |
47 |
|
|
// fprintf(stderr, "%s\n", msg); |
48 |
|
|
} |
49 |
|
|
|
50 |
|
|
int cvmfs_test_list(cvmfs_context *ctx, const char *path) |
51 |
|
|
{ |
52 |
|
|
if (ctx == NULL) { |
53 |
|
|
fprintf(stderr, "%s\n", "please attach a repo first!"); |
54 |
|
|
return -1; |
55 |
|
|
} |
56 |
|
|
|
57 |
|
|
char filepath[TEST_LINE_MAX]; |
58 |
|
|
struct stat info; |
59 |
|
|
|
60 |
|
|
char **buffer = 0; |
61 |
|
|
size_t length = 0; |
62 |
|
|
int i; |
63 |
|
|
|
64 |
|
|
int result = cvmfs_listdir(ctx, path, &buffer, &length); |
65 |
|
|
if (result < 0) { |
66 |
|
|
fprintf(stderr, "%s: %s\n", path, strerror(errno)); |
67 |
|
|
return -1; |
68 |
|
|
} |
69 |
|
|
|
70 |
|
|
|
71 |
|
|
for (i = 0; buffer[i]; i++) { |
72 |
|
|
snprintf(filepath, TEST_LINE_MAX, "%s/%s", path, buffer[i]); |
73 |
|
|
cvmfs_stat(ctx, filepath, &info); |
74 |
|
|
printf("%10" PRIu64 " %s\n", |
75 |
|
|
static_cast<uint64_t>(info.st_size), buffer[i]); |
76 |
|
|
} |
77 |
|
|
|
78 |
|
|
free(buffer); |
79 |
|
|
|
80 |
|
|
return 0; |
81 |
|
|
} |
82 |
|
|
|
83 |
|
|
int cvmfs_test_cat(cvmfs_context *ctx, const char *path) |
84 |
|
|
{ |
85 |
|
|
if (ctx == NULL) { |
86 |
|
|
fprintf(stderr, "%s\n", "please attach a repo first!"); |
87 |
|
|
return -1; |
88 |
|
|
} |
89 |
|
|
|
90 |
|
|
char buffer[TEST_LINE_MAX]; |
91 |
|
|
|
92 |
|
|
int fd = cvmfs_open(ctx, path); |
93 |
|
|
if (fd < 0) { |
94 |
|
|
fprintf(stderr, "%s: %s\n", path, strerror(errno)); |
95 |
|
|
return fd; |
96 |
|
|
} |
97 |
|
|
|
98 |
|
|
while (1) { |
99 |
|
|
int length = read(fd, buffer, sizeof(buffer)); |
100 |
|
|
if (length <= 0) break; |
101 |
|
|
int retval = write(1, buffer, length); |
102 |
|
|
assert(retval == length); |
103 |
|
|
} |
104 |
|
|
|
105 |
|
|
cvmfs_close(ctx, fd); |
106 |
|
|
|
107 |
|
|
return 0; |
108 |
|
|
} |
109 |
|
|
|
110 |
|
|
cvmfs_context* cvmfs_test_attach(const char *repo_name) |
111 |
|
|
{ |
112 |
|
|
cvmfs_context *ctx = NULL; |
113 |
|
|
|
114 |
|
|
RepoMap::const_iterator i = attached_repos.find(repo_name); |
115 |
|
|
if (i == attached_repos.end()) { |
116 |
|
|
std::string fqrn = std::string(repo_name) + ".cern.ch"; |
117 |
|
|
cvmfs_option_map *repo_opts = cvmfs_options_clone(cvmfs_opts); |
118 |
|
|
cvmfs_options_set(repo_opts, "CVMFS_SERVER_URL", |
119 |
|
|
"http://cvmfs-stratum-one.cern.ch/cvmfs/@fqrn@;" |
120 |
|
|
"http://cernvmfs.gridpp.rl.ac.uk/cvmfs/@fqrn@;" |
121 |
|
|
"http://cvmfs.racf.bnl.gov/cvmfs/@fqrn@"); |
122 |
|
|
cvmfs_options_set(repo_opts, "CVMFS_PUBLIC_KEY", |
123 |
|
|
"/etc/cvmfs/keys/cern.ch/cern.ch.pub"); |
124 |
|
|
|
125 |
|
|
char *repo_options_str = cvmfs_options_dump(repo_opts); |
126 |
|
|
printf("attaching repo with options:\n%s\n", repo_options_str); |
127 |
|
|
cvmfs_options_free(repo_options_str); |
128 |
|
|
cvmfs_errors retval = cvmfs_attach_repo_v2(fqrn.c_str(), repo_opts, &ctx); |
129 |
|
|
if (retval != LIBCVMFS_ERR_OK) { |
130 |
|
|
cvmfs_options_fini(repo_opts); |
131 |
|
|
fprintf(stderr, "couldn't initialize cvmfs!\n"); |
132 |
|
|
} else { |
133 |
|
|
// Let cvmfs_detach_repo free the options_map |
134 |
|
|
cvmfs_adopt_options(ctx, repo_opts); |
135 |
|
|
attached_repos[repo_name] = ctx; |
136 |
|
|
} |
137 |
|
|
} else { |
138 |
|
|
printf("switching to previously attached repo: %s\n", repo_name); |
139 |
|
|
ctx = i->second; |
140 |
|
|
} |
141 |
|
|
|
142 |
|
|
return ctx; |
143 |
|
|
} |
144 |
|
|
|
145 |
|
|
void cvmfs_test_detach(const char *repo_name, const cvmfs_context *active_ctx) { |
146 |
|
|
RepoMap::iterator i = attached_repos.find(repo_name); |
147 |
|
|
if (i == attached_repos.end()) { |
148 |
|
|
printf("Did not find '%s' to detach\n", repo_name); |
149 |
|
|
return; |
150 |
|
|
} |
151 |
|
|
|
152 |
|
|
cvmfs_context *ctx = i->second; |
153 |
|
|
if (ctx == active_ctx) { |
154 |
|
|
printf("'%s' is currently active and cannot be detached.\n", repo_name); |
155 |
|
|
return; |
156 |
|
|
} |
157 |
|
|
|
158 |
|
|
attached_repos.erase(i); |
159 |
|
|
cvmfs_detach_repo(ctx); |
160 |
|
|
} |
161 |
|
|
|
162 |
|
|
|
163 |
|
|
int main(int argc, char *argv[]) |
164 |
|
|
{ |
165 |
|
|
char line[TEST_LINE_MAX]; |
166 |
|
|
char path[TEST_LINE_MAX]; |
167 |
|
|
char repo_name[TEST_LINE_MAX]; |
168 |
|
|
|
169 |
|
|
cvmfs_set_log_fn(cvmfs_log_ignore); |
170 |
|
|
|
171 |
|
|
cvmfs_opts = cvmfs_options_init(); |
172 |
|
|
cvmfs_options_set(cvmfs_opts, "CVMFS_CACHE_DIR", "/tmp/test-libcvmfs-cache"); |
173 |
|
|
cvmfs_options_set(cvmfs_opts, "CVMFS_HTTP_PROXY", "DIRECT"); |
174 |
|
|
|
175 |
|
|
char *global_options_str = cvmfs_options_dump(cvmfs_opts); |
176 |
|
|
printf("%s: initializing with options:\n%s\n", argv[0], global_options_str); |
177 |
|
|
cvmfs_options_free(global_options_str); |
178 |
|
|
cvmfs_errors retval = cvmfs_init_v2(cvmfs_opts); |
179 |
|
|
if (retval != LIBCVMFS_ERR_OK) { |
180 |
|
|
cvmfs_options_fini(cvmfs_opts); |
181 |
|
|
fprintf(stderr, "couldn't initialize libcvmfs!\n"); |
182 |
|
|
return -1; |
183 |
|
|
} |
184 |
|
|
|
185 |
|
|
cvmfs_context *ctx = NULL; |
186 |
|
|
|
187 |
|
|
while (1) { |
188 |
|
|
printf("cvmfs> "); |
189 |
|
|
fflush(stdout); |
190 |
|
|
|
191 |
|
|
if (!fgets(line, sizeof(line), stdin)) break; |
192 |
|
|
|
193 |
|
|
line[strlen(line)-1] = 0; |
194 |
|
|
|
195 |
|
|
if (sscanf(line, "list %s", path) == 1) { |
196 |
|
|
cvmfs_test_list(ctx, path); |
197 |
|
|
} else if (sscanf(line, "cat %s", path) == 1) { |
198 |
|
|
cvmfs_test_cat(ctx, path); |
199 |
|
|
} else if (sscanf(line, "attach %s", repo_name) == 1) { |
200 |
|
|
ctx = cvmfs_test_attach(repo_name); |
201 |
|
|
} else if (sscanf(line, "detach %s", repo_name) == 1) { |
202 |
|
|
cvmfs_test_detach(repo_name, ctx); |
203 |
|
|
} else if (!strcmp(line, "quit")) { |
204 |
|
|
break; |
205 |
|
|
} else { |
206 |
|
|
cvmfs_test_help(); |
207 |
|
|
} |
208 |
|
|
} |
209 |
|
|
|
210 |
|
|
cvmfs_fini(); |
211 |
|
|
cvmfs_options_fini(cvmfs_opts); |
212 |
|
|
|
213 |
|
|
return 0; |
214 |
|
|
} |
215 |
|
|
|