Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / cls / lua / cls_lua.cc
1 /*
2  * Lua Bindings for RADOS Object Class
3  */
4 #include <errno.h>
5 #include <setjmp.h>
6 #include <string>
7 #include <sstream>
8 #include <lua.hpp>
9 #include "include/types.h"
10 #include "objclass/objclass.h"
11 #include "json_spirit/json_spirit.h"
12 #include "cls_lua.h"
13 #include "cls_lua_ops.h"
14
15 CLS_VER(1,0)
16 CLS_NAME(lua)
17
18 /*
19  * Jump point for recovering from Lua panic.
20  */
21 static jmp_buf cls_lua_panic_jump;
22
23 /*
24  * Handle Lua panic.
25  */
26 static int cls_lua_atpanic(lua_State *lua)
27 {
28   CLS_ERR("error: Lua panic: %s", lua_tostring(lua, -1));
29   longjmp(cls_lua_panic_jump, 1);
30   return 0;
31 }
32
33 struct clslua_err {
34   bool error;
35   int ret;
36 };
37
38 /*
39  * Input parameter encoding.
40  */
41 enum InputEncoding {
42   JSON_ENC,
43   BUFFERLIST_ENC,
44 };
45
46 struct clslua_hctx {
47   struct clslua_err error;
48   InputEncoding in_enc;
49   int ret;
50
51   cls_method_context_t *hctx;
52   bufferlist *inbl;   // raw cls input
53   bufferlist *outbl;  // raw cls output
54
55   string script;      // lua script
56   string handler;     // lua handler
57   bufferlist input;   // lua handler input
58 };
59
60 /* Lua registry key for method context */
61 static char clslua_hctx_reg_key;
62
63 /*
64  * Grabs the full method handler context
65  */
66 static clslua_hctx *__clslua_get_hctx(lua_State *L)
67 {
68   /* lookup registry value */
69   lua_pushlightuserdata(L, &clslua_hctx_reg_key);
70   lua_gettable(L, LUA_REGISTRYINDEX);
71
72   /* check cls_lua assumptions */
73   assert(!lua_isnil(L, -1));
74   assert(lua_type(L, -1) == LUA_TLIGHTUSERDATA);
75
76   /* cast and cleanup stack */
77   clslua_hctx *hctx = (struct clslua_hctx *)lua_touserdata(L, -1);
78   lua_pop(L, 1);
79
80   return hctx;
81 }
82
83 /*
84  * Get the method context out of the registry. This is called at the beginning
85  * of each clx_cxx_* wrapper, and must be set before there is any chance a Lua
86  * script calling a 'cls' module function that requires it.
87  */
88 static cls_method_context_t clslua_get_hctx(lua_State *L)
89 {
90   struct clslua_hctx *hctx = __clslua_get_hctx(L);
91   return *hctx->hctx;
92 }
93
94 /*
95  * Returns a reference to cls_lua error state from registry.
96  */
97 struct clslua_err *clslua_checkerr(lua_State *L)
98 {
99   struct clslua_hctx *hctx = __clslua_get_hctx(L);
100   struct clslua_err *err = &hctx->error;
101   return err;
102 }
103
104
105 /* Registry key for real `pcall` function */
106 static char clslua_pcall_reg_key;
107
108 /*
109  * Wrap Lua pcall to check for errors thrown by cls_lua (e.g. I/O errors or
110  * bufferlist decoding errors). The global error is cleared before returning
111  * to the caller.
112  */
113 static int clslua_pcall(lua_State *L)
114 {
115   int nargs = lua_gettop(L);
116   lua_pushlightuserdata(L, &clslua_pcall_reg_key);
117   lua_gettable(L, LUA_REGISTRYINDEX);
118   lua_insert(L, 1);
119   lua_call(L, nargs, LUA_MULTRET);
120   struct clslua_err *err = clslua_checkerr(L);
121   assert(err);
122   if (err->error) {
123     err->error = false;
124     lua_pushinteger(L, err->ret);
125     lua_insert(L, -2);
126   }
127   return lua_gettop(L);
128 }
129
130
131 /*
132  * cls_log
133  */
134 static int clslua_log(lua_State *L)
135 {
136   int nargs = lua_gettop(L);
137
138   if (!nargs)
139     return 0;
140
141   int loglevel = LOG_LEVEL_DEFAULT;
142   bool custom_ll = false;
143
144   /* check if first arg can be a log level */
145   if (nargs > 1 && lua_isnumber(L, 1)) {
146     int ll = (int)lua_tonumber(L, 1);
147     if (ll >= 0) {
148       loglevel = ll;
149       custom_ll = true;
150     }
151   }
152
153   /* check space for args and seperators (" ") */
154   int nelems = ((nargs - (custom_ll ? 1 : 0)) * 2) - 1;
155   luaL_checkstack(L, nelems, "rados.log(..)");
156
157   for (int i = custom_ll ? 2 : 1; i <= nargs; i++) {
158     const char *part = lua_tostring(L, i);
159     if (!part) {
160       if (lua_type(L, i) == LUA_TBOOLEAN)
161         part = lua_toboolean(L, i) ? "true" : "false";
162       else
163         part = luaL_typename(L, i);
164     }
165     lua_pushstring(L, part);
166     if ((i+1) <= nargs)
167       lua_pushstring(L, " ");
168   }
169
170   /* join string parts and send to Ceph/reply log */
171   lua_concat(L, nelems);
172   CLS_LOG(loglevel, "%s", lua_tostring(L, -1));
173
174   /* concat leaves result at top of stack */
175   return 1;
176 }
177
178 static char clslua_registered_handle_reg_key;
179
180 /*
181  * Register a function to be used as a handler target
182  */
183 static int clslua_register(lua_State *L)
184 {
185   luaL_checktype(L, 1, LUA_TFUNCTION);
186
187   /* get table of registered handlers */
188   lua_pushlightuserdata(L, &clslua_registered_handle_reg_key);
189   lua_gettable(L, LUA_REGISTRYINDEX);
190   assert(lua_type(L, -1) == LUA_TTABLE);
191
192   /* lookup function argument */
193   lua_pushvalue(L, 1);
194   lua_gettable(L, -2);
195
196   if (lua_isnil(L, -1)) {
197     lua_pushvalue(L, 1);
198     lua_pushvalue(L, 1);
199     lua_settable(L, -4);
200   } else {
201     lua_pushstring(L, "Cannot register handler more than once");
202     return lua_error(L);
203   }
204
205   return 0;
206 }
207
208 /*
209  * Check if a function is registered as a handler
210  */
211 static void clslua_check_registered_handler(lua_State *L)
212 {
213   luaL_checktype(L, -1, LUA_TFUNCTION);
214
215   /* get table of registered handlers */
216   lua_pushlightuserdata(L, &clslua_registered_handle_reg_key);
217   lua_gettable(L, LUA_REGISTRYINDEX);
218   assert(lua_type(L, -1) == LUA_TTABLE);
219
220   /* lookup function argument */
221   lua_pushvalue(L, -2);
222   lua_gettable(L, -2);
223
224   if (!lua_rawequal(L, -1, -3)) {
225     lua_pushstring(L, "Handler is not registered");
226     lua_error(L);
227   }
228
229   lua_pop(L, 2);
230 }
231
232 /*
233  * Handle result of a cls_cxx_* call. If @ok is non-zero then we return with
234  * the number of Lua return arguments on the stack. Otherwise we save error
235  * information in the registry and throw a Lua error.
236  */
237 static int clslua_opresult(lua_State *L, int ok, int ret, int nargs,
238     bool error_on_stack = false)
239 {
240   struct clslua_err *err = clslua_checkerr(L);
241
242   assert(err);
243   if (err->error) {
244     CLS_ERR("error: cls_lua state machine: unexpected error");
245     ceph_abort();
246   }
247
248   /* everything is cherry */
249   if (ok)
250     return nargs;
251
252   /* set error in registry */
253   err->error = true;
254   err->ret = ret;
255
256   /* push error message */
257   if (!error_on_stack)
258     lua_pushfstring(L, "%s", strerror(-ret));
259
260   return lua_error(L);
261 }
262
263 /*
264  * cls_cxx_create
265  */
266 static int clslua_create(lua_State *lua)
267 {
268   cls_method_context_t hctx = clslua_get_hctx(lua);
269   int exclusive = lua_toboolean(lua, 1);
270
271   int ret = cls_cxx_create(hctx, exclusive);
272   return clslua_opresult(lua, (ret == 0), ret, 0);
273 }
274
275 /*
276  * cls_cxx_remove
277  */
278 static int clslua_remove(lua_State *lua)
279 {
280   cls_method_context_t hctx = clslua_get_hctx(lua);
281
282   int ret = cls_cxx_remove(hctx);
283   return clslua_opresult(lua, (ret == 0), ret, 0);
284 }
285
286 /*
287  * cls_cxx_stat
288  */
289 static int clslua_stat(lua_State *L)
290 {
291   cls_method_context_t hctx = clslua_get_hctx(L);
292
293   uint64_t size;
294   time_t mtime;
295   int ret = cls_cxx_stat(hctx, &size, &mtime);
296   if (!ret) {
297     lua_pushinteger(L, size);
298     lua_pushinteger(L, mtime);
299   }
300   return clslua_opresult(L, (ret == 0), ret, 2);
301 }
302
303 /*
304  * cls_cxx_read
305  */
306 static int clslua_read(lua_State *L)
307 {
308   cls_method_context_t hctx = clslua_get_hctx(L);
309   int offset = luaL_checkinteger(L, 1);
310   int length = luaL_checkinteger(L, 2);
311   bufferlist *bl = clslua_pushbufferlist(L, NULL);
312   int ret = cls_cxx_read(hctx, offset, length, bl);
313   return clslua_opresult(L, (ret >= 0), ret, 1);
314 }
315
316 /*
317  * cls_cxx_write
318  */
319 static int clslua_write(lua_State *L)
320 {
321   cls_method_context_t hctx = clslua_get_hctx(L);
322   int offset = luaL_checkinteger(L, 1);
323   int length = luaL_checkinteger(L, 2);
324   bufferlist *bl = clslua_checkbufferlist(L, 3);
325   int ret = cls_cxx_write(hctx, offset, length, bl);
326   return clslua_opresult(L, (ret == 0), ret, 0);
327 }
328
329 /*
330  * cls_cxx_write_full
331  */
332 static int clslua_write_full(lua_State *L)
333 {
334   cls_method_context_t hctx = clslua_get_hctx(L);
335   bufferlist *bl = clslua_checkbufferlist(L, 1);
336   int ret = cls_cxx_write_full(hctx, bl);
337   return clslua_opresult(L, (ret == 0), ret, 0);
338 }
339
340 /*
341  * cls_cxx_getxattr
342  */
343 static int clslua_getxattr(lua_State *L)
344 {
345   cls_method_context_t hctx = clslua_get_hctx(L);
346   const char *name = luaL_checkstring(L, 1);
347   bufferlist  *bl = clslua_pushbufferlist(L, NULL);
348   int ret = cls_cxx_getxattr(hctx, name, bl);
349   return clslua_opresult(L, (ret >= 0), ret, 1);
350 }
351
352 /*
353  * cls_cxx_getxattrs
354  */
355 static int clslua_getxattrs(lua_State *L)
356 {
357   cls_method_context_t hctx = clslua_get_hctx(L);
358
359   map<string, bufferlist> attrs;
360   int ret = cls_cxx_getxattrs(hctx, &attrs);
361   if (ret < 0)
362     return clslua_opresult(L, 0, ret, 0);
363
364   lua_createtable(L, 0, attrs.size());
365
366   for (auto it = attrs.cbegin(); it != attrs.cend(); it++) {
367     lua_pushstring(L, it->first.c_str());
368     bufferlist  *bl = clslua_pushbufferlist(L, NULL);
369     *bl = it->second; // xfer ownership... will be GC'd
370     lua_settable(L, -3);
371   }
372
373   return clslua_opresult(L, 1, ret, 1);
374 }
375
376 /*
377  * cls_cxx_setxattr
378  */
379 static int clslua_setxattr(lua_State *L)
380 {
381   cls_method_context_t hctx = clslua_get_hctx(L);
382   const char *name = luaL_checkstring(L, 1);
383   bufferlist *bl = clslua_checkbufferlist(L, 2);
384   int ret = cls_cxx_setxattr(hctx, name, bl);
385   return clslua_opresult(L, (ret == 0), ret, 1);
386 }
387
388 /*
389  * cls_cxx_map_get_val
390  */
391 static int clslua_map_get_val(lua_State *L)
392 {
393   cls_method_context_t hctx = clslua_get_hctx(L);
394   const char *key = luaL_checkstring(L, 1);
395   bufferlist  *bl = clslua_pushbufferlist(L, NULL);
396   int ret = cls_cxx_map_get_val(hctx, key, bl);
397   return clslua_opresult(L, (ret == 0), ret, 1);
398 }
399
400 /*
401  * cls_cxx_map_set_val
402  */
403 static int clslua_map_set_val(lua_State *L)
404 {
405   cls_method_context_t hctx = clslua_get_hctx(L);
406   const char *key = luaL_checkstring(L, 1);
407   bufferlist *val = clslua_checkbufferlist(L, 2);
408   int ret = cls_cxx_map_set_val(hctx, key, val);
409   return clslua_opresult(L, (ret == 0), ret, 0);
410 }
411
412 /*
413  * cls_cxx_map_clear
414  */
415 static int clslua_map_clear(lua_State *L)
416 {
417   cls_method_context_t hctx = clslua_get_hctx(L);
418   int ret = cls_cxx_map_clear(hctx);
419   return clslua_opresult(L, (ret == 0), ret, 0);
420 }
421
422 /*
423  * cls_cxx_map_get_keys
424  */
425 static int clslua_map_get_keys(lua_State *L)
426 {
427   cls_method_context_t hctx = clslua_get_hctx(L);
428   const char *start_after = luaL_checkstring(L, 1);
429   int max_to_get = luaL_checkinteger(L, 2);
430
431   std::set<string> keys;
432   bool more;
433   int ret = cls_cxx_map_get_keys(hctx, start_after, max_to_get, &keys, &more);
434   if (ret < 0)
435     return clslua_opresult(L, 0, ret, 0);
436
437   lua_createtable(L, 0, keys.size());
438
439   for (auto it = keys.cbegin(); it != keys.cend(); it++) {
440     const std::string& key = *it;
441     lua_pushstring(L, key.c_str());
442     lua_pushboolean(L, 1);
443     lua_settable(L, -3);
444   }
445
446   return clslua_opresult(L, 1, ret, 1);
447 }
448
449 /*
450  * cls_cxx_map_get_vals
451  */
452 static int clslua_map_get_vals(lua_State *L)
453 {
454   cls_method_context_t hctx = clslua_get_hctx(L);
455   const char *start_after = luaL_checkstring(L, 1);
456   const char *filter_prefix= luaL_checkstring(L, 2);
457   int max_to_get = luaL_checkinteger(L, 3);
458
459   map<string, bufferlist> kvpairs;
460   bool more;
461   int ret = cls_cxx_map_get_vals(hctx, start_after, filter_prefix,
462       max_to_get, &kvpairs, &more);
463   if (ret < 0)
464     return clslua_opresult(L, 0, ret, 0);
465
466   lua_createtable(L, 0, kvpairs.size());
467
468   for (auto it = kvpairs.cbegin(); it != kvpairs.cend(); it++) {
469     lua_pushstring(L, it->first.c_str());
470     bufferlist  *bl = clslua_pushbufferlist(L, NULL);
471     *bl = it->second; // xfer ownership... will be GC'd
472     lua_settable(L, -3);
473   }
474
475   return clslua_opresult(L, 1, ret, 1);
476 }
477
478 /*
479  * cls_cxx_map_read_header
480  */
481 static int clslua_map_read_header(lua_State *L)
482 {
483   cls_method_context_t hctx = clslua_get_hctx(L);
484   bufferlist *bl = clslua_pushbufferlist(L, NULL);
485   int ret = cls_cxx_map_read_header(hctx, bl);
486   return clslua_opresult(L, (ret >= 0), ret, 1);
487 }
488
489 /*
490  * cls_cxx_map_write_header
491  */
492 static int clslua_map_write_header(lua_State *L)
493 {
494   cls_method_context_t hctx = clslua_get_hctx(L);
495   bufferlist *bl = clslua_checkbufferlist(L, 1);
496   int ret = cls_cxx_map_write_header(hctx, bl);
497   return clslua_opresult(L, (ret == 0), ret, 0);
498 }
499
500 /*
501  * cls_cxx_map_set_vals
502  */
503 static int clslua_map_set_vals(lua_State *L)
504 {
505   cls_method_context_t hctx = clslua_get_hctx(L);
506   luaL_checktype(L, 1, LUA_TTABLE);
507
508   map<string, bufferlist> kvpairs;
509
510   for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) {
511     /*
512      * In the case of a numeric key a copy is made on the stack because
513      * converting to a string would otherwise manipulate the original key and
514      * cause problems for iteration.
515      */
516     string key;
517     int type_code = lua_type(L, -2);
518     switch (type_code) {
519       case LUA_TSTRING:
520         key.assign(lua_tolstring(L, -2, NULL));
521         break;
522
523       case LUA_TNUMBER:
524         lua_pushvalue(L, -2);
525         key.assign(lua_tolstring(L, -1, NULL));
526         lua_pop(L, 1);
527         break;
528
529       default:
530         lua_pushfstring(L, "map_set_vals: invalid key type (%s)",
531             lua_typename(L, type_code));
532         return clslua_opresult(L, 0, -EINVAL, 0, true);
533     }
534
535     bufferlist val;
536     type_code = lua_type(L, -1);
537     switch (type_code) {
538       case LUA_TSTRING:
539         {
540           size_t len;
541           const char *data = lua_tolstring(L, -1, &len);
542           val.append(data, len);
543         }
544         break;
545
546       default:
547         lua_pushfstring(L, "map_set_vals: invalid val type (%s) for key (%s)",
548             lua_typename(L, type_code), key.c_str());
549         return clslua_opresult(L, 0, -EINVAL, 0, true);
550     }
551
552     kvpairs[key] = val;
553   }
554
555   int ret = cls_cxx_map_set_vals(hctx, &kvpairs);
556
557   return clslua_opresult(L, (ret == 0), ret, 0);
558 }
559
560 /*
561  * cls_cxx_map_remove_key
562  */
563 static int clslua_map_remove_key(lua_State *L)
564 {
565   cls_method_context_t hctx = clslua_get_hctx(L);
566   const char *key = luaL_checkstring(L, 1);
567   int ret = cls_cxx_map_remove_key(hctx, key);
568   return clslua_opresult(L, (ret == 0), ret, 0);
569 }
570
571 /*
572  * cls_current_version
573  */
574 static int clslua_current_version(lua_State *L)
575 {
576   cls_method_context_t hctx = clslua_get_hctx(L);
577   uint64_t version = cls_current_version(hctx);
578   lua_pushinteger(L, version);
579   return clslua_opresult(L, 1, 0, 1);
580 }
581
582 /*
583  * cls_current_subop_num
584  */
585 static int clslua_current_subop_num(lua_State *L)
586 {
587   cls_method_context_t hctx = clslua_get_hctx(L);
588   int num = cls_current_subop_num(hctx);
589   lua_pushinteger(L, num);
590   return clslua_opresult(L, 1, 0, 1);
591 }
592
593 /*
594  * cls_current_subop_version
595  */
596 static int clslua_current_subop_version(lua_State *L)
597 {
598   cls_method_context_t hctx = clslua_get_hctx(L);
599   string s;
600   cls_cxx_subop_version(hctx, &s);
601   lua_pushstring(L, s.c_str());
602   return clslua_opresult(L, 1, 0, 1);
603 }
604
605 /*
606  * Functions registered in the 'cls' module.
607  */
608 static const luaL_Reg clslua_lib[] = {
609   // mgmt
610   {"register", clslua_register},
611   {"log", clslua_log},
612
613   // data
614   {"create", clslua_create},
615   {"remove", clslua_remove},
616   {"stat", clslua_stat},
617   {"read", clslua_read},
618   {"write", clslua_write},
619   {"write_full", clslua_write_full},
620
621   // xattr
622   {"getxattr", clslua_getxattr},
623   {"getxattrs", clslua_getxattrs},
624   {"setxattr", clslua_setxattr},
625
626   // omap
627   {"map_clear", clslua_map_clear},
628   {"map_get_keys", clslua_map_get_keys},
629   {"map_get_vals", clslua_map_get_vals},
630   {"map_read_header", clslua_map_read_header},
631   {"map_write_header", clslua_map_write_header},
632   {"map_get_val", clslua_map_get_val},
633   {"map_set_val", clslua_map_set_val},
634   {"map_set_vals", clslua_map_set_vals},
635   {"map_remove_key", clslua_map_remove_key},
636
637   // env
638   {"current_version", clslua_current_version},
639   {"current_subop_num", clslua_current_subop_num},
640   {"current_subop_version", clslua_current_subop_version},
641
642   {NULL, NULL}
643 };
644
645 /*
646  * Set const int in table at top of stack
647  */
648 #define SET_INT_CONST(var) do { \
649   lua_pushinteger(L, var); \
650   lua_setfield(L, -2, #var); \
651 } while (0)
652
653 /*
654  *
655  */
656 static int luaopen_objclass(lua_State *L)
657 {
658   lua_newtable(L);
659
660   /*
661    * Register cls functions (cls.log, etc...)
662    */
663   luaL_setfuncs(L, clslua_lib, 0);
664
665   /*
666    * Register generic errno values under 'cls'
667    */
668   SET_INT_CONST(EPERM);
669   SET_INT_CONST(ENOENT);
670   SET_INT_CONST(ESRCH);
671   SET_INT_CONST(EINTR);
672   SET_INT_CONST(EIO);
673   SET_INT_CONST(ENXIO);
674   SET_INT_CONST(E2BIG);
675   SET_INT_CONST(ENOEXEC);
676   SET_INT_CONST(EBADF);
677   SET_INT_CONST(ECHILD);
678   SET_INT_CONST(EAGAIN);
679   SET_INT_CONST(ENOMEM);
680   SET_INT_CONST(EACCES);
681   SET_INT_CONST(EFAULT);
682   SET_INT_CONST(EBUSY);
683   SET_INT_CONST(EEXIST);
684   SET_INT_CONST(EXDEV);
685   SET_INT_CONST(ENODEV);
686   SET_INT_CONST(ENOTDIR);
687   SET_INT_CONST(EISDIR);
688   SET_INT_CONST(EINVAL);
689   SET_INT_CONST(ENFILE);
690   SET_INT_CONST(EMFILE);
691   SET_INT_CONST(ENOTTY);
692   SET_INT_CONST(EFBIG);
693   SET_INT_CONST(ENOSPC);
694   SET_INT_CONST(ESPIPE);
695   SET_INT_CONST(EROFS);
696   SET_INT_CONST(EMLINK);
697   SET_INT_CONST(EPIPE);
698   SET_INT_CONST(EDOM);
699   SET_INT_CONST(ERANGE);
700
701   return 1;
702 }
703
704 /*
705  * Setup the execution environment. Our sandbox currently is not
706  * sophisticated. With a new Lua state per-request we don't need to work about
707  * users stepping on each other, but we do rip out access to the local file
708  * system. All this will change when/if we decide to use some shared Lua
709  * states, most likely for performance reasons.
710  */
711 static void clslua_setup_env(lua_State *L)
712 {
713   luaL_requiref(L, "_G", luaopen_base, 1);
714   lua_pop(L, 1);
715
716   /*
717    * Wrap `pcall` to intercept errors. First save a reference to the default
718    * Lua `pcall` function, and then replace `pcall` with our version.
719    */
720   lua_pushlightuserdata(L, &clslua_pcall_reg_key);
721   lua_getglobal(L, "pcall");
722   lua_settable(L, LUA_REGISTRYINDEX);
723
724   lua_pushcfunction(L, clslua_pcall);
725   lua_setglobal(L, "pcall");
726
727   /* mask unsafe */
728   lua_pushnil(L);
729   lua_setglobal(L, "loadfile");
730
731   /* mask unsafe */
732   lua_pushnil(L);
733   lua_setglobal(L, "dofile");
734
735   /* not integrated into our error handling */
736   lua_pushnil(L);
737   lua_setglobal(L, "xpcall");
738
739   luaL_requiref(L, LUA_TABLIBNAME, luaopen_table, 1);
740   lua_pop(L, 1);
741
742   luaL_requiref(L, LUA_STRLIBNAME, luaopen_string, 1);
743   lua_pop(L, 1);
744
745   luaL_requiref(L, LUA_MATHLIBNAME, luaopen_math, 1);
746   lua_pop(L, 1);
747
748   luaL_requiref(L, "objclass", luaopen_objclass, 1);
749   lua_pop(L, 1);
750
751   luaL_requiref(L, "bufferlist", luaopen_bufferlist, 1);
752   lua_pop(L, 1);
753 }
754
755 /*
756  * Schema:
757  * {
758  *   "script": "...",
759  *   "handler": "...",
760  *   "input": "..." # optional
761  * }
762  */
763 static int unpack_json_command(lua_State *L, struct clslua_hctx *ctx,
764     std::string& script, std::string& handler, std::string& input,
765     size_t *input_len)
766 {
767   std::string json_input(ctx->inbl->c_str());
768   json_spirit::mValue value;
769
770   if (!json_spirit::read(json_input, value)) {
771     CLS_ERR("error: unparseable JSON");
772     ctx->ret = -EINVAL;
773     return 1;
774   }
775
776   if (value.type() != json_spirit::obj_type) {
777     CLS_ERR("error: input not a JSON object");
778     ctx->ret = -EINVAL;
779     return 1;
780   }
781   json_spirit::mObject obj = value.get_obj();
782
783   // grab the script
784   std::map<std::string, json_spirit::mValue>::const_iterator it = obj.find("script");
785   if (it == obj.end()) {
786     CLS_ERR("error: 'script' field found in JSON object");
787     ctx->ret = -EINVAL;
788     return 1;
789   }
790
791   if (it->second.type() != json_spirit::str_type) {
792     CLS_ERR("error: script is not a string");
793     ctx->ret = -EINVAL;
794     return 1;
795   }
796   script = it->second.get_str();
797
798   // grab the target function/handler name
799   it = obj.find("handler");
800   if (it == obj.end()) {
801     CLS_ERR("error: no target handler found in JSON object");
802     ctx->ret = -EINVAL;
803     return 1;
804   }
805
806   if (it->second.type() != json_spirit::str_type) {
807     CLS_ERR("error: target handler is not a string");
808     ctx->ret = -EINVAL;
809     return 1;
810   }
811   handler = it->second.get_str();
812
813   // grab the input (optional)
814   it = obj.find("input");
815   if (it != obj.end()) {
816     if (it->second.type() != json_spirit::str_type) {
817       CLS_ERR("error: handler input is not a string");
818       ctx->ret = -EINVAL;
819       return 1;
820     }
821     input = it->second.get_str();
822     *input_len = input.size();
823   }
824
825   return 0;
826 }
827
828 /*
829  * Runs the script, and calls handler.
830  */
831 static int clslua_eval(lua_State *L)
832 {
833   struct clslua_hctx *ctx = __clslua_get_hctx(L);
834   ctx->ret = -EIO; /* assume failure */
835
836   /*
837    * Load modules, errno value constants, and other environment goodies. Must
838    * be done before loading/compiling the chunk.
839    */
840   clslua_setup_env(L);
841
842   /*
843    * Deserialize the input that contains the script, the name of the handler
844    * to call, and the handler input.
845    */
846   switch (ctx->in_enc) {
847     case JSON_ENC:
848       {
849         std::string input_str;
850         size_t input_str_len = 0;
851
852         // if there is an error decoding json then ctx->ret will be set and we
853         // return normally from this function.
854         if (unpack_json_command(L, ctx, ctx->script, ctx->handler, input_str,
855               &input_str_len))
856           return 0;
857
858         bufferptr bp(input_str.c_str(), input_str_len);
859         ctx->input.push_back(bp);
860       }
861       break;
862
863     case BUFFERLIST_ENC:
864       {
865         cls_lua_eval_op op;
866
867         try {
868           bufferlist::iterator it = ctx->inbl->begin();
869           ::decode(op, it);
870         } catch (const buffer::error &err) {
871           CLS_ERR("error: could not decode ceph encoded input");
872           ctx->ret = -EINVAL;
873           return 0;
874         }
875
876         ctx->script.swap(op.script);
877         ctx->handler.swap(op.handler);
878         ctx->input = op.input;
879       }
880       break;
881
882     default:
883       CLS_ERR("error: unknown encoding type");
884       ctx->ret = -EFAULT;
885       ceph_abort();
886       return 0;
887   }
888
889   /*
890    * Create table to hold registered (valid) handlers.
891    *
892    * Must be done before running the script for the first time because the
893    * script will immediately try to register one or more handlers using
894    * cls.register(function), which depends on this table.
895    */
896   lua_pushlightuserdata(L, &clslua_registered_handle_reg_key);
897   lua_newtable(L);
898   lua_settable(L, LUA_REGISTRYINDEX);
899
900   /* load and compile chunk */
901   if (luaL_loadstring(L, ctx->script.c_str()))
902     return lua_error(L);
903
904   /* execute chunk */
905   lua_call(L, 0, 0);
906
907   /* no error, but nothing left to do */
908   if (!ctx->handler.size()) {
909     CLS_LOG(10, "no handler name provided");
910     ctx->ret = 0; /* success */
911     return 0;
912   }
913
914   lua_getglobal(L, ctx->handler.c_str());
915   if (lua_type(L, -1) != LUA_TFUNCTION) {
916     CLS_ERR("error: unknown handler or not function: %s", ctx->handler.c_str());
917     ctx->ret = -EOPNOTSUPP;
918     return 0;
919   }
920
921   /* throw error if function is not registered */
922   clslua_check_registered_handler(L);
923
924   /* setup the input/output bufferlists */
925   clslua_pushbufferlist(L, &ctx->input);
926   clslua_pushbufferlist(L, ctx->outbl);
927
928   /*
929    * Call the target Lua object class handler. If the call is successful then
930    * we will examine the return value here and store it in the context. Errors
931    * that occur are handled in the top-level eval() function.
932    */
933   int top = lua_gettop(L);
934   lua_call(L, 2, LUA_MULTRET);
935
936   /* store return value in context */
937   if (!(lua_gettop(L) + 3 - top))
938     lua_pushinteger(L, 0);
939   ctx->ret = luaL_checkinteger(L, -1);
940
941   return 0;
942 }
943
944 /*
945  * Main handler. Proxies the Lua VM and the Lua-defined handler.
946  */
947 static int eval_generic(cls_method_context_t hctx, bufferlist *in, bufferlist *out,
948     InputEncoding in_enc)
949 {
950   struct clslua_hctx ctx;
951   lua_State *L = NULL;
952   int ret = -EIO;
953
954   /* stash context for use in Lua VM */
955   ctx.hctx = &hctx;
956   ctx.inbl = in;
957   ctx.in_enc = in_enc;
958   ctx.outbl = out;
959   ctx.error.error = false;
960
961   /* build lua vm state */
962   L = luaL_newstate();
963   if (!L) {
964     CLS_ERR("error creating new Lua state");
965     goto out;
966   }
967
968   /* panic handler for unhandled errors */
969   lua_atpanic(L, &cls_lua_atpanic);
970
971   if (setjmp(cls_lua_panic_jump) == 0) {
972
973     /*
974      * Stash the handler context in the register. It contains the objclass
975      * method context, global error state, and the command and reply structs.
976      */
977     lua_pushlightuserdata(L, &clslua_hctx_reg_key);
978     lua_pushlightuserdata(L, &ctx);
979     lua_settable(L, LUA_REGISTRYINDEX);
980
981     /* Process the input and run the script */
982     lua_pushcfunction(L, clslua_eval);
983     ret = lua_pcall(L, 0, 0, 0);
984
985     /* Encountered an error? */
986     if (ret) {
987       struct clslua_err *err = clslua_checkerr(L);
988       if (!err) {
989         CLS_ERR("error: cls_lua state machine: unexpected error");
990         ceph_abort();
991       }
992
993       /* Error origin a cls_cxx_* method? */
994       if (err->error) {
995         ret = err->ret; /* cls_cxx_* return value */
996
997         /* Errors always abort. Fix up ret and log error */
998         if (ret >= 0) {
999           CLS_ERR("error: unexpected handler return value");
1000           ret = -EFAULT;
1001         }
1002
1003       } else
1004         ret = -EIO; /* Generic error code */
1005
1006       CLS_ERR("error: %s", lua_tostring(L, -1));
1007
1008     } else {
1009       /*
1010        * No Lua error encountered while running the script, but the handler
1011        * may still have returned an error code (e.g. an errno value).
1012        */
1013       ret = ctx.ret;
1014     }
1015
1016   } else {
1017     CLS_ERR("error: recovering from Lua panic");
1018     ret = -EFAULT;
1019   }
1020
1021 out:
1022   if (L)
1023     lua_close(L);
1024   return ret;
1025 }
1026
1027 static int eval_json(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
1028 {
1029   return eval_generic(hctx, in, out, JSON_ENC);
1030 }
1031
1032 static int eval_bufferlist(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
1033 {
1034   return eval_generic(hctx, in, out, BUFFERLIST_ENC);
1035 }
1036
1037 CLS_INIT(lua)
1038 {
1039   CLS_LOG(20, "Loaded lua class!");
1040
1041   cls_handle_t h_class;
1042   cls_method_handle_t h_eval_json;
1043   cls_method_handle_t h_eval_bufferlist;
1044
1045   cls_register("lua", &h_class);
1046
1047   cls_register_cxx_method(h_class, "eval_json",
1048       CLS_METHOD_RD | CLS_METHOD_WR, eval_json, &h_eval_json);
1049
1050   cls_register_cxx_method(h_class, "eval_bufferlist",
1051       CLS_METHOD_RD | CLS_METHOD_WR, eval_bufferlist, &h_eval_bufferlist);
1052 }