/** * Wrapper function to call the main conf functions. * The wrapper calls handles opening and closing of the * configuration. */ static int net_conf_wrap_function(struct net_context *c, int (*fn)(struct net_context *, struct smbconf_ctx *, int, const char **), int argc, const char **argv) { sbcErr err; TALLOC_CTX *mem_ctx = talloc_stackframe(); struct smbconf_ctx *conf_ctx; int ret = -1; err = smbconf_init(mem_ctx, &conf_ctx, "registry:"); if (!SBC_ERROR_IS_OK(err)) { talloc_free(mem_ctx); return -1; } ret = fn(c, conf_ctx, argc, argv); smbconf_shutdown(conf_ctx); talloc_free(mem_ctx); return ret; }
static NTSTATUS sc_smap_unexpose(struct messaging_context *msg_ctx, struct fss_sc_smap *sc_smap, bool delete_all) { NTSTATUS ret; struct smbconf_ctx *conf_ctx; sbcErr cerr; bool is_modified = false; TALLOC_CTX *tmp_ctx = talloc_new(sc_smap); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } cerr = smbconf_init(tmp_ctx, &conf_ctx, "registry"); if (!SBC_ERROR_IS_OK(cerr)) { DEBUG(0, ("failed registry smbconf init: %s\n", sbcErrorString(cerr))); ret = NT_STATUS_UNSUCCESSFUL; goto err_tmp; } /* registry IO must be done as root */ become_root(); cerr = smbconf_transaction_start(conf_ctx); if (!SBC_ERROR_IS_OK(cerr)) { DEBUG(0, ("error starting transaction: %s\n", sbcErrorString(cerr))); ret = NT_STATUS_UNSUCCESSFUL; goto err_conf; } while (sc_smap) { struct fss_sc_smap *sc_map_next = sc_smap->next; if (!smbconf_share_exists(conf_ctx, sc_smap->sc_share_name)) { DEBUG(2, ("no such share: %s\n", sc_smap->sc_share_name)); if (!delete_all) { ret = NT_STATUS_OK; goto err_cancel; } sc_smap = sc_map_next; continue; } cerr = smbconf_delete_share(conf_ctx, sc_smap->sc_share_name); if (!SBC_ERROR_IS_OK(cerr)) { DEBUG(0, ("error deleting share: %s\n", sbcErrorString(cerr))); ret = NT_STATUS_UNSUCCESSFUL; goto err_cancel; } is_modified = true; sc_smap->is_exposed = false; if (delete_all) { sc_smap = sc_map_next; } else { sc_smap = NULL; /* only process single sc_map entry */ } } if (is_modified) { cerr = smbconf_transaction_commit(conf_ctx); if (!SBC_ERROR_IS_OK(cerr)) { DEBUG(0, ("error committing transaction: %s\n", sbcErrorString(cerr))); ret = NT_STATUS_UNSUCCESSFUL; goto err_cancel; } message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL); } else { ret = NT_STATUS_OK; goto err_cancel; } ret = NT_STATUS_OK; err_conf: talloc_free(conf_ctx); unbecome_root(); err_tmp: talloc_free(tmp_ctx); return ret; err_cancel: smbconf_transaction_cancel(conf_ctx); talloc_free(conf_ctx); unbecome_root(); talloc_free(tmp_ctx); return ret; }
uint32_t _fss_ExposeShadowCopySet(struct pipes_struct *p, struct fss_ExposeShadowCopySet *r) { NTSTATUS status; struct fss_sc_set *sc_set; struct fss_sc *sc; uint32_t ret; struct smbconf_ctx *fconf_ctx; struct smbconf_ctx *rconf_ctx; sbcErr cerr; char *fconf_path; TALLOC_CTX *tmp_ctx = talloc_new(p->mem_ctx); if (tmp_ctx == NULL) { return HRES_ERROR_V(HRES_E_OUTOFMEMORY); } if (!fss_permitted(p)) { ret = HRES_ERROR_V(HRES_E_ACCESSDENIED); goto err_out; } sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId); if (sc_set == NULL) { ret = HRES_ERROR_V(HRES_E_INVALIDARG); goto err_out; } if (sc_set->state != FSS_SC_COMMITED) { ret = FSRVP_E_BAD_STATE; goto err_out; } /* stop message sequence timer */ TALLOC_FREE(fss_global.seq_tmr); /* * Prepare to clone the base share definition for the snapshot share. * Create both registry and file conf contexts, as the base share * definition may be located in either. The snapshot share definition * is always written to the registry. */ cerr = smbconf_init(tmp_ctx, &rconf_ctx, "registry"); if (!SBC_ERROR_IS_OK(cerr)) { DEBUG(0, ("failed registry smbconf init: %s\n", sbcErrorString(cerr))); ret = HRES_ERROR_V(HRES_E_FAIL); goto err_tmr_restart; } fconf_path = talloc_asprintf(tmp_ctx, "file:%s", get_dyn_CONFIGFILE()); if (fconf_path == NULL) { ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY); goto err_tmr_restart; } cerr = smbconf_init(tmp_ctx, &fconf_ctx, fconf_path); if (!SBC_ERROR_IS_OK(cerr)) { DEBUG(0, ("failed %s smbconf init: %s\n", fconf_path, sbcErrorString(cerr))); ret = HRES_ERROR_V(HRES_E_FAIL); goto err_tmr_restart; } /* registry IO must be done as root */ become_root(); cerr = smbconf_transaction_start(rconf_ctx); if (!SBC_ERROR_IS_OK(cerr)) { DEBUG(0, ("error starting transaction: %s\n", sbcErrorString(cerr))); ret = HRES_ERROR_V(HRES_E_FAIL); unbecome_root(); goto err_tmr_restart; } for (sc = sc_set->scs; sc; sc = sc->next) { ret = fss_sc_expose(fconf_ctx, rconf_ctx, tmp_ctx, sc); if (ret) { DEBUG(0,("failed to expose shadow copy of %s\n", sc->volume_name)); goto err_cancel; } } cerr = smbconf_transaction_commit(rconf_ctx); if (!SBC_ERROR_IS_OK(cerr)) { DEBUG(0, ("error committing transaction: %s\n", sbcErrorString(cerr))); ret = HRES_ERROR_V(HRES_E_FAIL); goto err_cancel; } unbecome_root(); message_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL); for (sc = sc_set->scs; sc; sc = sc->next) { struct fss_sc_smap *sm; for (sm = sc->smaps; sm; sm = sm->next) sm->is_exposed = true; } sc_set->state = FSS_SC_EXPOSED; become_root(); status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets, fss_global.sc_sets_count, fss_global.db_path); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("failed to store fss server state: %s\n", nt_errstr(status))); } /* start message sequence timer */ fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr); talloc_free(tmp_ctx); return 0; err_cancel: smbconf_transaction_cancel(rconf_ctx); unbecome_root(); err_tmr_restart: fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr); err_out: talloc_free(tmp_ctx); return ret; }
static int net_conf_import(struct net_context *c, struct smbconf_ctx *conf_ctx, int argc, const char **argv) { int ret = -1; const char *filename = NULL; const char *servicename = NULL; char *conf_source = NULL; TALLOC_CTX *mem_ctx; struct smbconf_ctx *txt_ctx; sbcErr err; if (c->display_usage) return net_conf_import_usage(c, argc, argv); mem_ctx = talloc_stackframe(); switch (argc) { case 0: default: net_conf_import_usage(c, argc, argv); goto done; case 2: servicename = talloc_strdup(mem_ctx, argv[1]); if (servicename == NULL) { d_printf(_("error: out of memory!\n")); goto done; } FALL_THROUGH; case 1: filename = argv[0]; break; } DEBUG(3,("net_conf_import: reading configuration from file %s.\n", filename)); conf_source = talloc_asprintf(mem_ctx, "file:%s", filename); if (conf_source == NULL) { d_printf(_("error: out of memory!\n")); goto done; } err = smbconf_init(mem_ctx, &txt_ctx, conf_source); if (!SBC_ERROR_IS_OK(err)) { d_printf(_("error loading file '%s': %s\n"), filename, sbcErrorString(err)); goto done; } if (c->opt_testmode) { d_printf(_("\nTEST MODE - " "would import the following configuration:\n\n")); } if (servicename != NULL) { struct smbconf_service *service = NULL; err = smbconf_get_share(txt_ctx, mem_ctx, servicename, &service); if (!SBC_ERROR_IS_OK(err)) { goto cancel; } err = smbconf_transaction_start(conf_ctx); if (!SBC_ERROR_IS_OK(err)) { d_printf(_("error starting transaction: %s\n"), sbcErrorString(err)); goto done; } err = import_process_service(c, conf_ctx, service); if (!SBC_ERROR_IS_OK(err)) { d_printf(_("error importing service %s: %s\n"), servicename, sbcErrorString(err)); goto cancel; } } else { struct smbconf_service **services = NULL; uint32_t num_shares, sidx; err = smbconf_get_config(txt_ctx, mem_ctx, &num_shares, &services); if (!SBC_ERROR_IS_OK(err)) { goto cancel; } if (!c->opt_testmode) { if (!SBC_ERROR_IS_OK(smbconf_drop(conf_ctx))) { goto cancel; } } /* * Wrap the importing of shares into a transaction, * but only 100 at a time, in order to save memory. * The allocated memory accumulates across the actions * within the transaction, and for me, some 1500 * imported shares, the MAX_TALLOC_SIZE of 256 MB * was exceeded. */ err = smbconf_transaction_start(conf_ctx); if (!SBC_ERROR_IS_OK(err)) { d_printf(_("error starting transaction: %s\n"), sbcErrorString(err)); goto done; } for (sidx = 0; sidx < num_shares; sidx++) { err = import_process_service(c, conf_ctx, services[sidx]); if (!SBC_ERROR_IS_OK(err)) { d_printf(_("error importing service %s: %s\n"), services[sidx]->name, sbcErrorString(err)); goto cancel; } if (sidx % 100) { continue; } err = smbconf_transaction_commit(conf_ctx); if (!SBC_ERROR_IS_OK(err)) { d_printf(_("error committing transaction: " "%s\n"), sbcErrorString(err)); goto done; } err = smbconf_transaction_start(conf_ctx); if (!SBC_ERROR_IS_OK(err)) { d_printf(_("error starting transaction: %s\n"), sbcErrorString(err)); goto done; } } } err = smbconf_transaction_commit(conf_ctx); if (!SBC_ERROR_IS_OK(err)) { d_printf(_("error committing transaction: %s\n"), sbcErrorString(err)); } else { ret = 0; } goto done; cancel: err = smbconf_transaction_cancel(conf_ctx); if (!SBC_ERROR_IS_OK(err)) { d_printf(_("error cancelling transaction: %s\n"), sbcErrorString(err)); } done: TALLOC_FREE(mem_ctx); return ret; }