LCOV - code coverage report
Current view: top level - source3/printing - printer_list.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 75 237 31.6 %
Date: 2024-04-21 15:09:00 Functions: 7 11 63.6 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Share Database of available printers.
       4             :    Copyright (C) Simo Sorce 2010
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "system/filesys.h"
      22             : #include "dbwrap/dbwrap.h"
      23             : #include "dbwrap/dbwrap_open.h"
      24             : #include "util_tdb.h"
      25             : #include "printer_list.h"
      26             : 
      27             : #define PL_KEY_PREFIX "PRINTERLIST/PRN/"
      28             : #define PL_KEY_FORMAT PL_KEY_PREFIX"%s"
      29             : #define PL_TIMESTAMP_KEY "PRINTERLIST/GLOBAL/LAST_REFRESH"
      30             : #define PL_DATA_FORMAT "ddPPP"
      31             : #define PL_TSTAMP_FORMAT "dd"
      32             : 
      33             : static struct db_context *printerlist_db;
      34             : 
      35        3368 : static struct db_context *get_printer_list_db(void)
      36             : {
      37           0 :         char *db_path;
      38             : 
      39        3368 :         if (printerlist_db != NULL) {
      40        3245 :                 return printerlist_db;
      41             :         }
      42             : 
      43         123 :         db_path = lock_path(talloc_tos(), "printer_list.tdb");
      44         123 :         if (db_path == NULL) {
      45           0 :                 return NULL;
      46             :         }
      47             : 
      48         123 :         printerlist_db = db_open(NULL,
      49             :                                  db_path,
      50             :                                  0,
      51             :                                  TDB_DEFAULT|TDB_INCOMPATIBLE_HASH,
      52             :                                  O_RDWR|O_CREAT,
      53             :                                  0644,
      54             :                                  DBWRAP_LOCK_ORDER_1,
      55             :                                  DBWRAP_FLAG_NONE);
      56         123 :         TALLOC_FREE(db_path);
      57         123 :         if (printerlist_db == NULL) {
      58           0 :                 DBG_ERR("Failed to open printer_list.tdb\n");
      59             :         }
      60         123 :         return printerlist_db;
      61             : }
      62             : 
      63        1192 : NTSTATUS printer_list_get_printer(TALLOC_CTX *mem_ctx,
      64             :                                   const char *name,
      65             :                                   const char **comment,
      66             :                                   const char **location,
      67             :                                   time_t *last_refresh)
      68             : {
      69           0 :         struct db_context *db;
      70           0 :         char *key;
      71           0 :         TDB_DATA data;
      72           0 :         uint32_t time_h, time_l;
      73        1192 :         char *nstr = NULL;
      74        1192 :         char *cstr = NULL;
      75        1192 :         char *lstr = NULL;
      76           0 :         NTSTATUS status;
      77           0 :         int ret;
      78             : 
      79        1192 :         db = get_printer_list_db();
      80        1192 :         if (db == NULL) {
      81           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
      82             :         }
      83             : 
      84        1192 :         key = talloc_asprintf(mem_ctx, PL_KEY_FORMAT, name);
      85        1192 :         if (!key) {
      86           0 :                 DEBUG(0, ("Failed to allocate key name!\n"));
      87           0 :                 return NT_STATUS_NO_MEMORY;
      88             :         }
      89             : 
      90        1192 :         status = dbwrap_fetch_bystring_upper(db, key, key, &data);
      91        1192 :         if (!NT_STATUS_IS_OK(status)) {
      92        1192 :                 DEBUG(6, ("Failed to fetch record! "
      93             :                           "The printer database is empty?\n"));
      94        1192 :                 goto done;
      95             :         }
      96             : 
      97           0 :         ret = tdb_unpack(data.dptr, data.dsize,
      98             :                          PL_DATA_FORMAT,
      99             :                          &time_h, &time_l, &nstr, &cstr, &lstr);
     100           0 :         if (ret == -1) {
     101           0 :                 DEBUG(1, ("Failed to unpack printer data\n"));
     102           0 :                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     103           0 :                 goto done;
     104             :         }
     105             : 
     106           0 :         if (last_refresh) {
     107           0 :                 *last_refresh = (time_t)(((uint64_t)time_h << 32) + time_l);
     108             :         }
     109             : 
     110           0 :         if (comment) {
     111           0 :                 *comment = talloc_strdup(mem_ctx, cstr);
     112           0 :                 if (!*comment) {
     113           0 :                         DEBUG(1, ("Failed to strdup comment!\n"));
     114           0 :                         status = NT_STATUS_NO_MEMORY;
     115           0 :                         goto done;
     116             :                 }
     117             :         }
     118             : 
     119           0 :         if (location) {
     120           0 :                 *location = talloc_strdup(mem_ctx, lstr);
     121           0 :                 if (*location == NULL) {
     122           0 :                         DEBUG(1, ("Failed to strdup location!\n"));
     123           0 :                         status = NT_STATUS_NO_MEMORY;
     124           0 :                         goto done;
     125             :                 }
     126             :         }
     127             : 
     128           0 :         status = NT_STATUS_OK;
     129             : 
     130        1192 : done:
     131        1192 :         SAFE_FREE(nstr);
     132        1192 :         SAFE_FREE(cstr);
     133        1192 :         SAFE_FREE(lstr);
     134        1192 :         TALLOC_FREE(key);
     135        1192 :         return status;
     136             : }
     137             : 
     138           0 : bool printer_list_printername_exists(const char *name)
     139             : {
     140           0 :         struct db_context *db = get_printer_list_db();
     141           0 :         char *key = NULL;
     142           0 :         bool ok;
     143             : 
     144           0 :         if (db == NULL) {
     145           0 :                 return false;
     146             :         }
     147             : 
     148           0 :         key = talloc_asprintf_strupper_m(
     149             :                 talloc_tos(), PL_KEY_FORMAT, name);
     150           0 :         if (key == NULL) {
     151           0 :                 return false;
     152             :         }
     153             : 
     154           0 :         ok = dbwrap_exists(db, string_term_tdb_data(key));
     155           0 :         TALLOC_FREE(key);
     156           0 :         return ok;
     157             : }
     158             : 
     159           0 : NTSTATUS printer_list_set_printer(TALLOC_CTX *mem_ctx,
     160             :                                   const char *name,
     161             :                                   const char *comment,
     162             :                                   const char *location,
     163             :                                   time_t last_refresh)
     164             : {
     165           0 :         struct db_context *db;
     166           0 :         char *key;
     167           0 :         TDB_DATA data;
     168           0 :         uint64_t time_64;
     169           0 :         uint32_t time_h, time_l;
     170           0 :         NTSTATUS status;
     171           0 :         int len;
     172             : 
     173           0 :         db = get_printer_list_db();
     174           0 :         if (db == NULL) {
     175           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     176             :         }
     177             : 
     178           0 :         key = talloc_asprintf(mem_ctx, PL_KEY_FORMAT, name);
     179           0 :         if (!key) {
     180           0 :                 DEBUG(0, ("Failed to allocate key name!\n"));
     181           0 :                 return NT_STATUS_NO_MEMORY;
     182             :         }
     183             : 
     184           0 :         if (comment == NULL) {
     185           0 :                 comment = "";
     186             :         }
     187             : 
     188           0 :         if (location == NULL) {
     189           0 :                 location = "";
     190             :         }
     191             : 
     192           0 :         time_64 = last_refresh;
     193           0 :         time_l = time_64 & 0xFFFFFFFFL;
     194           0 :         time_h = time_64 >> 32;
     195             : 
     196           0 :         len = tdb_pack(NULL, 0,
     197             :                        PL_DATA_FORMAT,
     198             :                        time_h,
     199             :                        time_l,
     200             :                        name,
     201             :                        comment,
     202             :                        location);
     203             : 
     204           0 :         data.dptr = talloc_array(key, uint8_t, len);
     205           0 :         if (!data.dptr) {
     206           0 :                 DEBUG(0, ("Failed to allocate tdb data buffer!\n"));
     207           0 :                 status = NT_STATUS_NO_MEMORY;
     208           0 :                 goto done;
     209             :         }
     210           0 :         data.dsize = len;
     211             : 
     212           0 :         len = tdb_pack(data.dptr, data.dsize,
     213             :                        PL_DATA_FORMAT,
     214             :                        time_h,
     215             :                        time_l,
     216             :                        name,
     217             :                        comment,
     218             :                        location);
     219             : 
     220           0 :         status = dbwrap_store_bystring_upper(db, key, data, TDB_REPLACE);
     221             : 
     222           0 : done:
     223           0 :         TALLOC_FREE(key);
     224           0 :         return status;
     225             : }
     226             : 
     227        1940 : NTSTATUS printer_list_get_last_refresh(time_t *last_refresh)
     228             : {
     229           0 :         struct db_context *db;
     230           0 :         TDB_DATA data;
     231           0 :         uint32_t time_h, time_l;
     232           0 :         NTSTATUS status;
     233           0 :         int ret;
     234             : 
     235        1940 :         db = get_printer_list_db();
     236        1940 :         if (db == NULL) {
     237           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     238             :         }
     239             : 
     240        1940 :         ZERO_STRUCT(data);
     241             : 
     242        1940 :         status = dbwrap_fetch_bystring(db, talloc_tos(), PL_TIMESTAMP_KEY, &data);
     243        1940 :         if (!NT_STATUS_IS_OK(status)) {
     244         120 :                 DEBUG(1, ("Failed to fetch record!\n"));
     245         120 :                 goto done;
     246             :         }
     247             : 
     248        1820 :         ret = tdb_unpack(data.dptr, data.dsize,
     249             :                          PL_TSTAMP_FORMAT, &time_h, &time_l);
     250        1820 :         TALLOC_FREE(data.dptr);
     251        1820 :         if (ret == -1) {
     252           0 :                 DEBUG(1, ("Failed to unpack printer data\n"));
     253           0 :                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     254           0 :                 goto done;
     255             :         }
     256             : 
     257        1820 :         *last_refresh = (time_t)(((uint64_t)time_h << 32) + time_l);
     258        1820 :         status = NT_STATUS_OK;
     259             : 
     260        1940 : done:
     261        1940 :         return status;
     262             : }
     263             : 
     264         118 : NTSTATUS printer_list_mark_reload(void)
     265             : {
     266           0 :         struct db_context *db;
     267           0 :         TDB_DATA data;
     268           0 :         uint32_t time_h, time_l;
     269         118 :         time_t now = time_mono(NULL);
     270           0 :         NTSTATUS status;
     271           0 :         int len;
     272             : 
     273         118 :         db = get_printer_list_db();
     274         118 :         if (db == NULL) {
     275           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     276             :         }
     277             : 
     278         118 :         time_l = ((uint64_t)now) & 0xFFFFFFFFL;
     279         118 :         time_h = ((uint64_t)now) >> 32;
     280             : 
     281         118 :         len = tdb_pack(NULL, 0, PL_TSTAMP_FORMAT, time_h, time_l);
     282             : 
     283         118 :         data.dptr = talloc_array(talloc_tos(), uint8_t, len);
     284         118 :         if (!data.dptr) {
     285           0 :                 DEBUG(0, ("Failed to allocate tdb data buffer!\n"));
     286           0 :                 status = NT_STATUS_NO_MEMORY;
     287           0 :                 goto done;
     288             :         }
     289         118 :         data.dsize = len;
     290             : 
     291         118 :         len = tdb_pack(data.dptr, data.dsize,
     292             :                        PL_TSTAMP_FORMAT, time_h, time_l);
     293             : 
     294         118 :         status = dbwrap_store_bystring(db, PL_TIMESTAMP_KEY,
     295             :                                                 data, TDB_REPLACE);
     296             : 
     297         118 : done:
     298         118 :         TALLOC_FREE(data.dptr);
     299         118 :         return status;
     300             : }
     301             : 
     302             : typedef int (printer_list_trv_fn_t)(struct db_record *, void *);
     303             : 
     304         118 : static NTSTATUS printer_list_traverse(printer_list_trv_fn_t *fn,
     305             :                                       void *private_data,
     306             :                                       bool read_only)
     307             : {
     308           0 :         struct db_context *db;
     309           0 :         NTSTATUS status;
     310             : 
     311         118 :         db = get_printer_list_db();
     312         118 :         if (db == NULL) {
     313           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     314             :         }
     315             : 
     316         118 :         if (read_only) {
     317           0 :                 status = dbwrap_traverse_read(db, fn, private_data, NULL);
     318             :         } else {
     319         118 :                 status = dbwrap_traverse(db, fn, private_data, NULL);
     320             :         }
     321             : 
     322         118 :         return status;
     323             : }
     324             : 
     325             : struct printer_list_clean_state {
     326             :         time_t last_refresh;
     327             :         NTSTATUS status;
     328             : };
     329             : 
     330         118 : static int printer_list_clean_fn(struct db_record *rec, void *private_data)
     331             : {
     332         118 :         struct printer_list_clean_state *state =
     333             :                         (struct printer_list_clean_state *)private_data;
     334           0 :         uint32_t time_h, time_l;
     335           0 :         time_t refresh;
     336           0 :         char *name;
     337           0 :         char *comment;
     338           0 :         char *location;
     339           0 :         int ret;
     340           0 :         TDB_DATA key;
     341           0 :         TDB_DATA value;
     342             : 
     343         118 :         key = dbwrap_record_get_key(rec);
     344             : 
     345             :         /* skip anything that does not contain PL_DATA_FORMAT data */
     346         118 :         if (strncmp((char *)key.dptr,
     347             :                     PL_KEY_PREFIX, sizeof(PL_KEY_PREFIX)-1)) {
     348         118 :                 return 0;
     349             :         }
     350             : 
     351           0 :         value = dbwrap_record_get_value(rec);
     352             : 
     353           0 :         ret = tdb_unpack(value.dptr, value.dsize,
     354             :                          PL_DATA_FORMAT, &time_h, &time_l, &name, &comment,
     355             :                          &location);
     356           0 :         if (ret == -1) {
     357           0 :                 DEBUG(1, ("Failed to unpack printer data\n"));
     358           0 :                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     359           0 :                 return -1;
     360             :         }
     361             : 
     362           0 :         SAFE_FREE(name);
     363           0 :         SAFE_FREE(comment);
     364           0 :         SAFE_FREE(location);
     365             : 
     366           0 :         refresh = (time_t)(((uint64_t)time_h << 32) + time_l);
     367             : 
     368           0 :         if (refresh < state->last_refresh) {
     369           0 :                 state->status = dbwrap_record_delete(rec);
     370           0 :                 if (!NT_STATUS_IS_OK(state->status)) {
     371           0 :                         return -1;
     372             :                 }
     373             :         }
     374             : 
     375           0 :         return 0;
     376             : }
     377             : 
     378         118 : NTSTATUS printer_list_clean_old(void)
     379             : {
     380           0 :         struct printer_list_clean_state state;
     381           0 :         NTSTATUS status;
     382             : 
     383         118 :         status = printer_list_get_last_refresh(&state.last_refresh);
     384         118 :         if (!NT_STATUS_IS_OK(status)) {
     385           0 :                 return status;
     386             :         }
     387             : 
     388         118 :         state.status = NT_STATUS_OK;
     389             : 
     390         118 :         status = printer_list_traverse(printer_list_clean_fn, &state, false);
     391         118 :         if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL) &&
     392           0 :             !NT_STATUS_IS_OK(state.status)) {
     393           0 :                 status = state.status;
     394             :         }
     395             : 
     396         118 :         return status;
     397             : }
     398             : 
     399             : struct printer_list_exec_state {
     400             :         void (*fn)(const char *, const char *, const char *, void *);
     401             :         void *private_data;
     402             :         NTSTATUS status;
     403             : };
     404             : 
     405           0 : static int printer_list_exec_fn(struct db_record *rec, void *private_data)
     406             : {
     407           0 :         struct printer_list_exec_state *state =
     408             :                         (struct printer_list_exec_state *)private_data;
     409           0 :         uint32_t time_h, time_l;
     410           0 :         char *name;
     411           0 :         char *comment;
     412           0 :         char *location;
     413           0 :         int ret;
     414           0 :         TDB_DATA key;
     415           0 :         TDB_DATA value;
     416             : 
     417           0 :         key = dbwrap_record_get_key(rec);
     418             : 
     419             :         /* always skip PL_TIMESTAMP_KEY key */
     420           0 :         if (strequal((const char *)key.dptr, PL_TIMESTAMP_KEY)) {
     421           0 :                 return 0;
     422             :         }
     423             : 
     424           0 :         value = dbwrap_record_get_value(rec);
     425             : 
     426           0 :         ret = tdb_unpack(value.dptr, value.dsize,
     427             :                          PL_DATA_FORMAT, &time_h, &time_l, &name, &comment,
     428             :                          &location);
     429           0 :         if (ret == -1) {
     430           0 :                 DEBUG(1, ("Failed to unpack printer data\n"));
     431           0 :                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     432           0 :                 return -1;
     433             :         }
     434             : 
     435           0 :         state->fn(name, comment, location, state->private_data);
     436             : 
     437           0 :         SAFE_FREE(name);
     438           0 :         SAFE_FREE(comment);
     439           0 :         SAFE_FREE(location);
     440           0 :         return 0;
     441             : }
     442             : 
     443           0 : NTSTATUS printer_list_read_run_fn(void (*fn)(const char *, const char *, const char *, void *),
     444             :                                   void *private_data)
     445             : {
     446           0 :         struct printer_list_exec_state state;
     447           0 :         NTSTATUS status;
     448             : 
     449           0 :         state.fn = fn;
     450           0 :         state.private_data = private_data;
     451           0 :         state.status = NT_STATUS_OK;
     452             : 
     453           0 :         status = printer_list_traverse(printer_list_exec_fn, &state, true);
     454           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL) &&
     455           0 :             !NT_STATUS_IS_OK(state.status)) {
     456           0 :                 status = state.status;
     457             :         }
     458             : 
     459           0 :         return status;
     460             : }

Generated by: LCOV version 1.14