root/source3/torture/vfstest.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_client_fd
  2. completion_fn
  3. next_command
  4. cmd_conf
  5. cmd_help
  6. cmd_debuglevel
  7. cmd_freemem
  8. cmd_quit
  9. add_command_set
  10. do_cmd
  11. process_cmd
  12. process_file
  13. exit_server
  14. exit_server_cleanly
  15. smbd_server_fd
  16. reload_printers
  17. reload_services
  18. smbd_event_context
  19. smbd_messaging_context
  20. smbd_memcache
  21. main

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    VFS module tester
   4 
   5    Copyright (C) Simo Sorce 2002
   6    Copyright (C) Eric Lorimer 2002
   7    Copyright (C) Jelmer Vernooij 2002,2003
   8 
   9    Most of this code was ripped off of rpcclient.
  10    Copyright (C) Tim Potter 2000-2001
  11 
  12    This program is free software; you can redistribute it and/or modify
  13    it under the terms of the GNU General Public License as published by
  14    the Free Software Foundation; either version 3 of the License, or
  15    (at your option) any later version.
  16    
  17    This program is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21    
  22    You should have received a copy of the GNU General Public License
  23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  24 */
  25 
  26 #include "includes.h"
  27 #include "vfstest.h"
  28 
  29 /* List to hold groups of commands */
  30 static struct cmd_list {
  31         struct cmd_list *prev, *next;
  32         struct cmd_set *cmd_set;
  33 } *cmd_list;
  34 
  35 int get_client_fd(void)
     /* [<][>][^][v][top][bottom][index][help] */
  36 {
  37         return -1;
  38 }
  39 
  40 /****************************************************************************
  41 handle completion of commands for readline
  42 ****************************************************************************/
  43 static char **completion_fn(const char *text, int start, int end)
     /* [<][>][^][v][top][bottom][index][help] */
  44 {
  45 #define MAX_COMPLETIONS 100
  46         char **matches;
  47         int i, count=0;
  48         struct cmd_list *commands = cmd_list;
  49 
  50         if (start) 
  51                 return NULL;
  52 
  53         /* make sure we have a list of valid commands */
  54         if (!commands) 
  55                 return NULL;
  56 
  57         matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
  58         if (!matches) return NULL;
  59 
  60         matches[count++] = SMB_STRDUP(text);
  61         if (!matches[0]) return NULL;
  62 
  63         while (commands && count < MAX_COMPLETIONS-1) 
  64         {
  65                 if (!commands->cmd_set)
  66                         break;
  67                 
  68                 for (i=0; commands->cmd_set[i].name; i++)
  69                 {
  70                         if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
  71                                 commands->cmd_set[i].fn) 
  72                         {
  73                                 matches[count] = SMB_STRDUP(commands->cmd_set[i].name);
  74                                 if (!matches[count]) 
  75                                         return NULL;
  76                                 count++;
  77                         }
  78                 }
  79                 
  80                 commands = commands->next;
  81                 
  82         }
  83 
  84         if (count == 2) {
  85                 SAFE_FREE(matches[0]);
  86                 matches[0] = SMB_STRDUP(matches[1]);
  87         }
  88         matches[count] = NULL;
  89         return matches;
  90 }
  91 
  92 static char *next_command(TALLOC_CTX *ctx, char **cmdstr)
     /* [<][>][^][v][top][bottom][index][help] */
  93 {
  94         char *command;
  95         char *p;
  96 
  97         if (!cmdstr || !(*cmdstr))
  98                 return NULL;
  99 
 100         p = strchr_m(*cmdstr, ';');
 101         if (p)
 102                 *p = '\0';
 103         command = talloc_strdup(ctx, *cmdstr);
 104         *cmdstr = p;
 105 
 106         return command;
 107 }
 108 
 109 /* Load specified configuration file */
 110 static NTSTATUS cmd_conf(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 111                         int argc, const char **argv)
 112 {
 113         if (argc != 2) {
 114                 printf("Usage: %s <smb.conf>\n", argv[0]);
 115                 return NT_STATUS_OK;
 116         }
 117 
 118         if (!lp_load(argv[1], False, True, False, True)) {
 119                 printf("Error loading \"%s\"\n", argv[1]);
 120                 return NT_STATUS_OK;
 121         }
 122 
 123         printf("\"%s\" successfully loaded\n", argv[1]);
 124         return NT_STATUS_OK;
 125 }
 126         
 127 /* Display help on commands */
 128 static NTSTATUS cmd_help(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 129                          int argc, const char **argv)
 130 {
 131         struct cmd_list *tmp;
 132         struct cmd_set *tmp_set;
 133 
 134         /* Usage */
 135         if (argc > 2) {
 136                 printf("Usage: %s [command]\n", argv[0]);
 137                 return NT_STATUS_OK;
 138         }
 139 
 140         /* Help on one command */
 141 
 142         if (argc == 2) {
 143                 for (tmp = cmd_list; tmp; tmp = tmp->next) {
 144                         
 145                         tmp_set = tmp->cmd_set;
 146 
 147                         while(tmp_set->name) {
 148                                 if (strequal(argv[1], tmp_set->name)) {
 149                                         if (tmp_set->usage &&
 150                                             tmp_set->usage[0])
 151                                                 printf("%s\n", tmp_set->usage);
 152                                         else
 153                                                 printf("No help for %s\n", tmp_set->name);
 154 
 155                                         return NT_STATUS_OK;
 156                                 }
 157 
 158                                 tmp_set++;
 159                         }
 160                 }
 161 
 162                 printf("No such command: %s\n", argv[1]);
 163                 return NT_STATUS_OK;
 164         }
 165 
 166         /* List all commands */
 167 
 168         for (tmp = cmd_list; tmp; tmp = tmp->next) {
 169 
 170                 tmp_set = tmp->cmd_set;
 171 
 172                 while(tmp_set->name) {
 173 
 174                         printf("%15s\t\t%s\n", tmp_set->name,
 175                                tmp_set->description ? tmp_set->description:
 176                                "");
 177 
 178                         tmp_set++;
 179                 }
 180         }
 181 
 182         return NT_STATUS_OK;
 183 }
 184 
 185 /* Change the debug level */
 186 static NTSTATUS cmd_debuglevel(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 187 {
 188         if (argc > 2) {
 189                 printf("Usage: %s [debuglevel]\n", argv[0]);
 190                 return NT_STATUS_OK;
 191         }
 192 
 193         if (argc == 2) {
 194                 DEBUGLEVEL = atoi(argv[1]);
 195         }
 196 
 197         printf("debuglevel is %d\n", DEBUGLEVEL);
 198 
 199         return NT_STATUS_OK;
 200 }
 201 
 202 static NTSTATUS cmd_freemem(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 203 {
 204         /* Cleanup */
 205         talloc_destroy(mem_ctx);
 206         mem_ctx = NULL;
 207         vfs->data = NULL;
 208         vfs->data_size = 0;
 209         return NT_STATUS_OK;
 210 }
 211 
 212 static NTSTATUS cmd_quit(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 213 {
 214         /* Cleanup */
 215         talloc_destroy(mem_ctx);
 216 
 217         exit(0);
 218         return NT_STATUS_OK; /* NOTREACHED */
 219 }
 220 
 221 static struct cmd_set vfstest_commands[] = {
 222 
 223         { "GENERAL OPTIONS" },
 224 
 225         { "conf",       cmd_conf,       "Load smb configuration file", "conf <smb.conf>" },
 226         { "help",       cmd_help,       "Get help on commands", "" },
 227         { "?",          cmd_help,       "Get help on commands", "" },
 228         { "debuglevel", cmd_debuglevel, "Set debug level", "" },
 229         { "freemem",    cmd_freemem,    "Free currently allocated buffers", "" },
 230         { "exit",       cmd_quit,       "Exit program", "" },
 231         { "quit",       cmd_quit,       "Exit program", "" },
 232 
 233         { NULL }
 234 };
 235 
 236 static struct cmd_set separator_command[] = {
 237         { "---------------", NULL,      "----------------------" },
 238         { NULL }
 239 };
 240 
 241 
 242 extern struct cmd_set vfs_commands[];
 243 static struct cmd_set *vfstest_command_list[] = {
 244         vfstest_commands,
 245         vfs_commands,
 246         NULL
 247 };
 248 
 249 static void add_command_set(struct cmd_set *cmd_set)
     /* [<][>][^][v][top][bottom][index][help] */
 250 {
 251         struct cmd_list *entry;
 252 
 253         if (!(entry = SMB_MALLOC_P(struct cmd_list))) {
 254                 DEBUG(0, ("out of memory\n"));
 255                 return;
 256         }
 257 
 258         ZERO_STRUCTP(entry);
 259 
 260         entry->cmd_set = cmd_set;
 261         DLIST_ADD(cmd_list, entry);
 262 }
 263 
 264 static NTSTATUS do_cmd(struct vfs_state *vfs, struct cmd_set *cmd_entry, char *cmd)
     /* [<][>][^][v][top][bottom][index][help] */
 265 {
 266         const char *p = cmd;
 267         char **argv = NULL;
 268         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 269         char *buf;
 270         TALLOC_CTX *mem_ctx = talloc_stackframe();
 271         int argc = 0, i;
 272 
 273         /* Count number of arguments first time through the loop then
 274            allocate memory and strdup them. */
 275 
 276  again:
 277         while(next_token_talloc(mem_ctx, &p, &buf, " ")) {
 278                 if (argv) {
 279                         argv[argc] = SMB_STRDUP(buf);
 280                 }
 281                 argc++;
 282         }
 283 
 284         if (!argv) {
 285                 /* Create argument list */
 286 
 287                 argv = SMB_MALLOC_ARRAY(char *, argc);
 288                 memset(argv, 0, sizeof(char *) * argc);
 289 
 290                 if (!argv) {
 291                         fprintf(stderr, "out of memory\n");
 292                         result = NT_STATUS_NO_MEMORY;
 293                         goto done;
 294                 }
 295 
 296                 p = cmd;
 297                 argc = 0;
 298 
 299                 goto again;
 300         }
 301 
 302         /* Call the function */
 303 
 304         if (cmd_entry->fn) {
 305                 /* Run command */
 306                 result = cmd_entry->fn(vfs, mem_ctx, argc, (const char **)argv);
 307         } else {
 308                 fprintf (stderr, "Invalid command\n");
 309                 goto done;
 310         }
 311 
 312  done:
 313 
 314         /* Cleanup */
 315 
 316         if (argv) {
 317                 for (i = 0; i < argc; i++)
 318                         SAFE_FREE(argv[i]);
 319 
 320                 SAFE_FREE(argv);
 321         }
 322 
 323         TALLOC_FREE(mem_ctx);
 324         return result;
 325 }
 326 
 327 /* Process a command entered at the prompt or as part of -c */
 328 static NTSTATUS process_cmd(struct vfs_state *vfs, char *cmd)
     /* [<][>][^][v][top][bottom][index][help] */
 329 {
 330         struct cmd_list *temp_list;
 331         bool found = False;
 332         char *buf;
 333         const char *p = cmd;
 334         NTSTATUS result = NT_STATUS_OK;
 335         TALLOC_CTX *mem_ctx = talloc_stackframe();
 336         int len = 0;
 337 
 338         if (cmd[strlen(cmd) - 1] == '\n')
 339                 cmd[strlen(cmd) - 1] = '\0';
 340 
 341         if (!next_token_talloc(mem_ctx, &p, &buf, " ")) {
 342                 TALLOC_FREE(mem_ctx);
 343                 return NT_STATUS_OK;
 344         }
 345 
 346         /* Strip the trailing \n if it exists */
 347         len = strlen(buf);
 348         if (buf[len-1] == '\n')
 349                 buf[len-1] = '\0';
 350 
 351         /* Search for matching commands */
 352 
 353         for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) {
 354                 struct cmd_set *temp_set = temp_list->cmd_set;
 355 
 356                 while(temp_set->name) {
 357                         if (strequal(buf, temp_set->name)) {
 358                                 found = True;
 359                                 result = do_cmd(vfs, temp_set, cmd);
 360 
 361                                 goto done;
 362                         }
 363                         temp_set++;
 364                 }
 365         }
 366 
 367  done:
 368         if (!found && buf[0]) {
 369                 printf("command not found: %s\n", buf);
 370                 TALLOC_FREE(mem_ctx);
 371                 return NT_STATUS_OK;
 372         }
 373 
 374         if (!NT_STATUS_IS_OK(result)) {
 375                 printf("result was %s\n", nt_errstr(result));
 376         }
 377 
 378         TALLOC_FREE(mem_ctx);
 379         return result;
 380 }
 381 
 382 static void process_file(struct vfs_state *pvfs, char *filename) {
     /* [<][>][^][v][top][bottom][index][help] */
 383         FILE *file;
 384         char command[3 * PATH_MAX];
 385 
 386         if (*filename == '-') {
 387                 file = stdin;
 388         } else {
 389                 file = fopen(filename, "r");
 390                 if (file == NULL) {
 391                         printf("vfstest: error reading file (%s)!", filename);
 392                         printf("errno n.%d: %s", errno, strerror(errno));
 393                         exit(-1);
 394                 }
 395         }
 396 
 397         while (fgets(command, 3 * PATH_MAX, file) != NULL) {
 398                 process_cmd(pvfs, command);
 399         }
 400 }
 401 
 402 void exit_server(const char *reason)
     /* [<][>][^][v][top][bottom][index][help] */
 403 {
 404         DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));
 405         exit(0);
 406 }
 407 
 408 void exit_server_cleanly(const char *const reason)
     /* [<][>][^][v][top][bottom][index][help] */
 409 {
 410         exit_server("normal exit");
 411 }
 412 
 413 static int server_fd = -1;
 414 int last_message = -1;
 415 
 416 int smbd_server_fd(void)
     /* [<][>][^][v][top][bottom][index][help] */
 417 {
 418                 return server_fd;
 419 }
 420 
 421 void reload_printers(void)
     /* [<][>][^][v][top][bottom][index][help] */
 422 {
 423         return;
 424 }
 425 
 426 /****************************************************************************
 427  Reload the services file.
 428 **************************************************************************/
 429 
 430 bool reload_services(bool test)
     /* [<][>][^][v][top][bottom][index][help] */
 431 {
 432         bool ret;
 433 
 434         if (lp_loaded()) {
 435                 const char *fname = lp_configfile();
 436                 if (file_exist(fname) &&
 437                     !strcsequal(fname, get_dyn_CONFIGFILE())) {
 438                         set_dyn_CONFIGFILE(fname);
 439                         test = False;
 440                 }
 441         }
 442 
 443         reopen_logs();
 444 
 445         if (test && !lp_file_list_changed())
 446                 return(True);
 447 
 448         lp_killunused(conn_snum_used);
 449 
 450         ret = lp_load(get_dyn_CONFIGFILE(), False, False, True, True);
 451 
 452         /* perhaps the config filename is now set */
 453         if (!test)
 454                 reload_services(True);
 455 
 456         reopen_logs();
 457 
 458         load_interfaces();
 459 
 460         {
 461                 if (smbd_server_fd() != -1) {      
 462                         set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
 463                         set_socket_options(smbd_server_fd(),
 464                                            lp_socket_options());
 465                 }
 466         }
 467 
 468         mangle_reset_cache();
 469         reset_stat_cache();
 470 
 471         /* this forces service parameters to be flushed */
 472         set_current_service(NULL,0,True);
 473 
 474         return (ret);
 475 }
 476 
 477 struct event_context *smbd_event_context(void)
     /* [<][>][^][v][top][bottom][index][help] */
 478 {
 479         static struct event_context *ctx;
 480 
 481         if (!ctx && !(ctx = event_context_init(NULL))) {
 482                 smb_panic("Could not init smbd event context\n");
 483         }
 484         return ctx;
 485 }
 486 
 487 struct messaging_context *smbd_messaging_context(void)
     /* [<][>][^][v][top][bottom][index][help] */
 488 {
 489         static struct messaging_context *ctx;
 490 
 491         if (!ctx && !(ctx = messaging_init(NULL, server_id_self(),
 492                                            smbd_event_context()))) {
 493                 smb_panic("Could not init smbd messaging context\n");
 494         }
 495         return ctx;
 496 }
 497 
 498 struct memcache *smbd_memcache(void)
     /* [<][>][^][v][top][bottom][index][help] */
 499 {
 500         static struct memcache *cache;
 501 
 502         if (!cache
 503             && !(cache = memcache_init(NULL,
 504                                        lp_max_stat_cache_size()*1024))) {
 505 
 506                 smb_panic("Could not init smbd memcache");
 507         }
 508         return cache;
 509 }
 510 
 511 /* Main function */
 512 
 513 int main(int argc, char *argv[])
     /* [<][>][^][v][top][bottom][index][help] */
 514 {
 515         static char             *cmdstr = NULL;
 516         struct cmd_set          **cmd_set;
 517         static struct vfs_state vfs;
 518         int i;
 519         static char             *filename = NULL;
 520         TALLOC_CTX *frame = talloc_stackframe();
 521 
 522         /* make sure the vars that get altered (4th field) are in
 523            a fixed location or certain compilers complain */
 524         poptContext pc;
 525         struct poptOption long_options[] = {
 526                 POPT_AUTOHELP
 527                 {"file",        'f', POPT_ARG_STRING,   &filename, 0, },
 528                 {"command",     'c', POPT_ARG_STRING,   &cmdstr, 0, "Execute specified list of commands" },
 529                 POPT_COMMON_SAMBA
 530                 POPT_TABLEEND
 531         };
 532 
 533         load_case_tables();
 534 
 535         setlinebuf(stdout);
 536 
 537         pc = poptGetContext("vfstest", argc, (const char **) argv,
 538                             long_options, 0);
 539         
 540         while(poptGetNextOpt(pc) != -1);
 541 
 542 
 543         poptFreeContext(pc);
 544 
 545         /* TODO: check output */
 546         reload_services(False);
 547 
 548         /* the following functions are part of the Samba debugging
 549            facilities.  See lib/debug.c */
 550         setup_logging("vfstest", True);
 551         
 552         /* Load command lists */
 553 
 554         cmd_set = vfstest_command_list;
 555 
 556         while(*cmd_set) {
 557                 add_command_set(*cmd_set);
 558                 add_command_set(separator_command);
 559                 cmd_set++;
 560         }
 561 
 562         /* some basic initialization stuff */
 563         sec_init();
 564         conn_init();
 565         vfs.conn = conn_new();
 566         for (i=0; i < 1024; i++)
 567                 vfs.files[i] = NULL;
 568 
 569         /* some advanced initiliazation stuff */
 570         smbd_vfs_init(vfs.conn);
 571 
 572         /* Do we have a file input? */
 573         if (filename && filename[0]) {
 574                 process_file(&vfs, filename);
 575                 return 0;
 576         }
 577 
 578         /* Do anything specified with -c */
 579         if (cmdstr && cmdstr[0]) {
 580                 char    *cmd;
 581                 char    *p = cmdstr;
 582 
 583                 while((cmd=next_command(frame, &p)) != NULL) {
 584                         process_cmd(&vfs, cmd);
 585                 }
 586 
 587                 TALLOC_FREE(cmd);
 588                 return 0;
 589         }
 590 
 591         /* Loop around accepting commands */
 592 
 593         while(1) {
 594                 char *line = NULL;
 595 
 596                 line = smb_readline("vfstest $> ", NULL, completion_fn);
 597 
 598                 if (line == NULL) {
 599                         break;
 600                 }
 601 
 602                 if (line[0] != '\n') {
 603                         process_cmd(&vfs, line);
 604                 }
 605                 SAFE_FREE(line);
 606         }
 607 
 608         conn_free(vfs.conn);
 609         TALLOC_FREE(frame);
 610         return 0;
 611 }

/* [<][>][^][v][top][bottom][index][help] */