1 /*
2  * getlocks_test.c : show all repository locks living below a URL
3  *
4  * ====================================================================
5  *    Licensed to the Apache Software Foundation (ASF) under one
6  *    or more contributor license agreements.  See the NOTICE file
7  *    distributed with this work for additional information
8  *    regarding copyright ownership.  The ASF licenses this file
9  *    to you under the Apache License, Version 2.0 (the
10  *    "License"); you may not use this file except in compliance
11  *    with the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  *    Unless required by applicable law or agreed to in writing,
16  *    software distributed under the License is distributed on an
17  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18  *    KIND, either express or implied.  See the License for the
19  *    specific language governing permissions and limitations
20  *    under the License.
21  * ====================================================================
22  *
23  *  To compile on unix against Subversion and APR libraries, try
24  *  something like:
25  *
26  *  cc getlocks_test.c -o getlocks_test \
27  *  -I/usr/local/include/subversion-1 -I/usr/local/apache2/include \
28  *  -L/usr/local/apache2/lib -L/usr/local/lib \
29  *  -lsvn_client-1 -lsvn_ra-1 -lsvn_subr-1 -lapr-0 -laprutil-0
30  *
31  */
32 
33 #include "svn_client.h"
34 #include "svn_pools.h"
35 #include "svn_config.h"
36 #include "svn_cmdline.h"
37 #include "svn_time.h"
38 #include "svn_fs.h"
39 #include "svn_path.h"
40 
41 /* Display a prompt and read a one-line response into the provided buffer,
42    removing a trailing newline if present. */
43 static svn_error_t *
prompt_and_read_line(const char * prompt,char * buffer,size_t max)44 prompt_and_read_line(const char *prompt,
45                      char *buffer,
46                      size_t max)
47 {
48   int len;
49   printf("%s: ", prompt);
50   if (fgets(buffer, max, stdin) == NULL)
51     return svn_error_create(0, NULL, "error reading stdin");
52   len = strlen(buffer);
53   if (len > 0 && buffer[len-1] == '\n')
54     buffer[len-1] = 0;
55   return SVN_NO_ERROR;
56 }
57 
58 /* A tiny callback function of type 'svn_auth_simple_prompt_func_t'. For
59    a much better example, see svn_cl__auth_simple_prompt in the official
60    svn cmdline client. */
61 static svn_error_t *
my_simple_prompt_callback(svn_auth_cred_simple_t ** cred,void * baton,const char * realm,const char * username,svn_boolean_t may_save,apr_pool_t * pool)62 my_simple_prompt_callback (svn_auth_cred_simple_t **cred,
63                            void *baton,
64                            const char *realm,
65                            const char *username,
66                            svn_boolean_t may_save,
67                            apr_pool_t *pool)
68 {
69   svn_auth_cred_simple_t *ret = apr_pcalloc (pool, sizeof (*ret));
70   char answerbuf[100];
71 
72   if (realm)
73     {
74       printf ("Authentication realm: %s\n", realm);
75     }
76 
77   if (username)
78     ret->username = apr_pstrdup (pool, username);
79   else
80     {
81       SVN_ERR (prompt_and_read_line("Username", answerbuf, sizeof(answerbuf)));
82       ret->username = apr_pstrdup (pool, answerbuf);
83     }
84 
85   SVN_ERR (prompt_and_read_line("Password", answerbuf, sizeof(answerbuf)));
86   ret->password = apr_pstrdup (pool, answerbuf);
87 
88   *cred = ret;
89   return SVN_NO_ERROR;
90 }
91 
92 
93 /* A tiny callback function of type 'svn_auth_username_prompt_func_t'. For
94    a much better example, see svn_cl__auth_username_prompt in the official
95    svn cmdline client. */
96 static svn_error_t *
my_username_prompt_callback(svn_auth_cred_username_t ** cred,void * baton,const char * realm,svn_boolean_t may_save,apr_pool_t * pool)97 my_username_prompt_callback (svn_auth_cred_username_t **cred,
98                              void *baton,
99                              const char *realm,
100                              svn_boolean_t may_save,
101                              apr_pool_t *pool)
102 {
103   svn_auth_cred_username_t *ret = apr_pcalloc (pool, sizeof (*ret));
104   char answerbuf[100];
105 
106   if (realm)
107     {
108       printf ("Authentication realm: %s\n", realm);
109     }
110 
111   SVN_ERR (prompt_and_read_line("Username", answerbuf, sizeof(answerbuf)));
112   ret->username = apr_pstrdup (pool, answerbuf);
113 
114   *cred = ret;
115   return SVN_NO_ERROR;
116 }
117 
118 
119 /* A callback function used when the RA layer needs a handle to a
120    temporary file.  This is a reduced version of the callback used in
121    the official svn cmdline client. */
122 static svn_error_t *
open_tmp_file(apr_file_t ** fp,void * callback_baton,apr_pool_t * pool)123 open_tmp_file (apr_file_t **fp,
124                void *callback_baton,
125                apr_pool_t *pool)
126 {
127   const char *path;
128   const char *ignored_filename;
129 
130   SVN_ERR (svn_io_temp_dir (&path, pool));
131   path = svn_path_join (path, "tempfile", pool);
132 
133   /* Open a unique file, with delete-on-close set. */
134   SVN_ERR (svn_io_open_unique_file2 (fp, &ignored_filename,
135                                      path, ".tmp",
136                                      svn_io_file_del_on_close, pool));
137 
138   return SVN_NO_ERROR;
139 }
140 
141 
142 
143 int
main(int argc,const char ** argv)144 main (int argc, const char **argv)
145 {
146   apr_pool_t *pool;
147   svn_error_t *err;
148   apr_hash_t *locks;
149   apr_hash_index_t *hi;
150   const char *URL;
151   svn_ra_session_t *session;
152   svn_ra_callbacks_t *cbtable;
153   apr_hash_t *cfg_hash;
154   svn_auth_baton_t *auth_baton;
155 
156   if (argc <= 1)
157     {
158       printf ("Usage:  %s URL\n", argv[0]);
159       printf ("    Print all locks at or below URL.\n");
160       return EXIT_FAILURE;
161     }
162   URL = argv[1];
163 
164   /* Initialize the app.  Send all error messages to 'stderr'.  */
165   if (svn_cmdline_init ("ra_test", stderr) != EXIT_SUCCESS)
166     return EXIT_FAILURE;
167 
168   /* Create top-level memory pool. Be sure to read the HACKING file to
169      understand how to properly use/free subpools. */
170   pool = svn_pool_create (NULL);
171 
172   /* Initialize the FS library. */
173   err = svn_fs_initialize (pool);
174   if (err) goto hit_error;
175 
176   /* Make sure the ~/.subversion run-time config files exist, and load. */
177   err = svn_config_ensure (NULL, pool);
178   if (err) goto hit_error;
179 
180   err = svn_config_get_config (&cfg_hash, NULL, pool);
181   if (err) goto hit_error;
182 
183   /* Build an authentication baton. */
184   {
185     /* There are many different kinds of authentication back-end
186        "providers".  See svn_auth.h for a full overview. */
187     svn_auth_provider_object_t *provider;
188     apr_array_header_t *providers
189       = apr_array_make (pool, 4, sizeof (svn_auth_provider_object_t *));
190 
191     svn_client_get_simple_prompt_provider (&provider,
192                                            my_simple_prompt_callback,
193                                            NULL, /* baton */
194                                            2, /* retry limit */ pool);
195     APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider;
196 
197     svn_client_get_username_prompt_provider (&provider,
198                                              my_username_prompt_callback,
199                                              NULL, /* baton */
200                                              2, /* retry limit */ pool);
201     APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider;
202 
203     /* Register the auth-providers into the context's auth_baton. */
204     svn_auth_open (&auth_baton, providers, pool);
205   }
206 
207   /* Create a table of callbacks for the RA session, mostly nonexistent. */
208   cbtable = apr_pcalloc (pool, sizeof(*cbtable));
209   cbtable->auth_baton = auth_baton;
210   cbtable->open_tmp_file = open_tmp_file;
211 
212   /* Now do the real work. */
213 
214   err = svn_ra_open (&session, URL, cbtable, NULL, cfg_hash, pool);
215   if (err) goto hit_error;
216 
217   err = svn_ra_get_locks (session, &locks, "", pool);
218   if (err) goto hit_error;
219 
220   err = svn_cmdline_printf (pool, "\n");
221   if (err) goto hit_error;
222 
223   for (hi = apr_hash_first (pool, locks); hi; hi = apr_hash_next (hi))
224     {
225       const void *key;
226       void *val;
227       const char *path, *cr_date, *exp_date;
228       svn_lock_t *lock;
229 
230       apr_hash_this (hi, &key, NULL, &val);
231       path = key;
232       lock = val;
233 
234       cr_date = svn_time_to_human_cstring (lock->creation_date, pool);
235 
236       if (lock->expiration_date)
237         exp_date = svn_time_to_human_cstring (lock->expiration_date, pool);
238       else
239         exp_date = "never";
240 
241       err = svn_cmdline_printf (pool, "%s\n", path);
242       if (err) goto hit_error;
243 
244       err = svn_cmdline_printf (pool,
245                                 "     UUID Token: %s\n", lock->token);
246       if (err) goto hit_error;
247 
248       err = svn_cmdline_printf (pool,
249                                 "          Owner: %s\n", lock->owner);
250       if (err) goto hit_error;
251 
252       err = svn_cmdline_printf (pool,
253                                 "        Comment: %s\n",
254                                 lock->comment ? lock->comment : "none");
255       if (err) goto hit_error;
256 
257       err = svn_cmdline_printf (pool,
258                                 "        Created: %s\n", cr_date);
259       if (err) goto hit_error;
260 
261       err = svn_cmdline_printf (pool,
262                                 "        Expires: %s\n\n", exp_date);
263       if (err) goto hit_error;
264     }
265 
266   return EXIT_SUCCESS;
267 
268  hit_error:
269   svn_handle_error2 (err, stderr, FALSE, "getlocks_test: ");
270   return EXIT_FAILURE;
271 }
272