~lefteris-nikoltsios/+junk/samba-lp1016895

« back to all changes in this revision

Viewing changes to source3/printing/printer_list.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.h"
 
23
#include "util_tdb.h"
 
24
#include "printer_list.h"
 
25
 
 
26
#define PL_DB_NAME() lock_path("printer_list.tdb")
 
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 *get_printer_list_db(void)
 
34
{
 
35
        static struct db_context *db;
 
36
 
 
37
        if (db != NULL) {
 
38
                return db;
 
39
        }
 
40
        db = db_open(NULL, PL_DB_NAME(), 0,
 
41
                     TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
 
42
                     O_RDWR|O_CREAT, 0644);
 
43
        return db;
 
44
}
 
45
 
 
46
bool printer_list_parent_init(void)
 
47
{
 
48
        struct db_context *db;
 
49
 
 
50
        /*
 
51
         * Open the tdb in the parent process (smbd) so that our
 
52
         * CLEAR_IF_FIRST optimization in tdb_reopen_all can properly
 
53
         * work.
 
54
         */
 
55
 
 
56
        db = get_printer_list_db();
 
57
        if (db == NULL) {
 
58
                DEBUG(1, ("could not open Printer List Database: %s\n",
 
59
                          strerror(errno)));
 
60
                return false;
 
61
        }
 
62
        return true;
 
63
}
 
64
 
 
65
NTSTATUS printer_list_get_printer(TALLOC_CTX *mem_ctx,
 
66
                                  const char *name,
 
67
                                  const char **comment,
 
68
                                  const char **location,
 
69
                                  time_t *last_refresh)
 
70
{
 
71
        struct db_context *db;
 
72
        char *key;
 
73
        TDB_DATA data;
 
74
        uint32_t time_h, time_l;
 
75
        char *nstr = NULL;
 
76
        char *cstr = NULL;
 
77
        char *lstr = NULL;
 
78
        NTSTATUS status;
 
79
        int ret;
 
80
 
 
81
        db = get_printer_list_db();
 
82
        if (db == NULL) {
 
83
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
84
        }
 
85
 
 
86
        key = talloc_asprintf(mem_ctx, PL_KEY_FORMAT, name);
 
87
        if (!key) {
 
88
                DEBUG(0, ("Failed to allocate key name!\n"));
 
89
                return NT_STATUS_NO_MEMORY;
 
90
        }
 
91
 
 
92
        data = dbwrap_fetch_bystring_upper(db, key, key);
 
93
        if (data.dptr == NULL) {
 
94
                DEBUG(1, ("Failed to fetch record!\n"));
 
95
                status = NT_STATUS_NOT_FOUND;
 
96
                goto done;
 
97
        }
 
98
 
 
99
        ret = tdb_unpack(data.dptr, data.dsize,
 
100
                         PL_DATA_FORMAT,
 
101
                         &time_h, &time_l, &nstr, &cstr, &lstr);
 
102
        if (ret == -1) {
 
103
                DEBUG(1, ("Failed to un pack printer data"));
 
104
                status = NT_STATUS_INTERNAL_DB_CORRUPTION;
 
105
                goto done;
 
106
        }
 
107
 
 
108
        if (last_refresh) {
 
109
                *last_refresh = (time_t)(((uint64_t)time_h << 32) + time_l);
 
110
        }
 
111
 
 
112
        if (comment) {
 
113
                *comment = talloc_strdup(mem_ctx, cstr);
 
114
                if (!*comment) {
 
115
                        DEBUG(1, ("Failed to strdup comment!\n"));
 
116
                        status = NT_STATUS_NO_MEMORY;
 
117
                        goto done;
 
118
                }
 
119
        }
 
120
 
 
121
        if (location) {
 
122
                *location = talloc_strdup(mem_ctx, lstr);
 
123
                if (*location == NULL) {
 
124
                        DEBUG(1, ("Failed to strdup location!\n"));
 
125
                        status = NT_STATUS_NO_MEMORY;
 
126
                        goto done;
 
127
                }
 
128
        }
 
129
 
 
130
        status = NT_STATUS_OK;
 
131
 
 
132
done:
 
133
        SAFE_FREE(nstr);
 
134
        SAFE_FREE(cstr);
 
135
        TALLOC_FREE(key);
 
136
        return status;
 
137
}
 
138
 
 
139
NTSTATUS printer_list_set_printer(TALLOC_CTX *mem_ctx,
 
140
                                  const char *name,
 
141
                                  const char *comment,
 
142
                                  const char *location,
 
143
                                  time_t last_refresh)
 
144
{
 
145
        struct db_context *db;
 
146
        char *key;
 
147
        TDB_DATA data;
 
148
        uint64_t time_64;
 
149
        uint32_t time_h, time_l;
 
150
        const char *str = NULL;
 
151
        const char *str2 = NULL;
 
152
        NTSTATUS status;
 
153
        int len;
 
154
 
 
155
        db = get_printer_list_db();
 
156
        if (db == NULL) {
 
157
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
158
        }
 
159
 
 
160
        key = talloc_asprintf(mem_ctx, PL_KEY_FORMAT, name);
 
161
        if (!key) {
 
162
                DEBUG(0, ("Failed to allocate key name!\n"));
 
163
                return NT_STATUS_NO_MEMORY;
 
164
        }
 
165
 
 
166
        if (comment) {
 
167
                str = comment;
 
168
        } else {
 
169
                str = "";
 
170
        }
 
171
 
 
172
        if (location) {
 
173
                str2 = location;
 
174
        } else {
 
175
                str2 = "";
 
176
        }
 
177
 
 
178
 
 
179
        time_64 = last_refresh;
 
180
        time_l = time_64 & 0xFFFFFFFFL;
 
181
        time_h = time_64 >> 32;
 
182
 
 
183
        len = tdb_pack(NULL, 0, PL_DATA_FORMAT, time_h, time_l, name, str, str2);
 
184
 
 
185
        data.dptr = talloc_array(key, uint8_t, len);
 
186
        if (!data.dptr) {
 
187
                DEBUG(0, ("Failed to allocate tdb data buffer!\n"));
 
188
                status = NT_STATUS_NO_MEMORY;
 
189
                goto done;
 
190
        }
 
191
        data.dsize = len;
 
192
 
 
193
        len = tdb_pack(data.dptr, data.dsize,
 
194
                       PL_DATA_FORMAT, time_h, time_l, name, str);
 
195
 
 
196
        status = dbwrap_store_bystring_upper(db, key, data, TDB_REPLACE);
 
197
 
 
198
done:
 
199
        TALLOC_FREE(key);
 
200
        return status;
 
201
}
 
202
 
 
203
NTSTATUS printer_list_get_last_refresh(time_t *last_refresh)
 
204
{
 
205
        struct db_context *db;
 
206
        TDB_DATA data;
 
207
        uint32_t time_h, time_l;
 
208
        NTSTATUS status;
 
209
        int ret;
 
210
 
 
211
        db = get_printer_list_db();
 
212
        if (db == NULL) {
 
213
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
214
        }
 
215
 
 
216
        ZERO_STRUCT(data);
 
217
 
 
218
        data = dbwrap_fetch_bystring(db, talloc_tos(), PL_TIMESTAMP_KEY);
 
219
        if (data.dptr == NULL) {
 
220
                DEBUG(1, ("Failed to fetch record!\n"));
 
221
                status = NT_STATUS_NOT_FOUND;
 
222
                goto done;
 
223
        }
 
224
 
 
225
        ret = tdb_unpack(data.dptr, data.dsize,
 
226
                         PL_TSTAMP_FORMAT, &time_h, &time_l);
 
227
        if (ret == -1) {
 
228
                DEBUG(1, ("Failed to un pack printer data"));
 
229
                status = NT_STATUS_INTERNAL_DB_CORRUPTION;
 
230
                goto done;
 
231
        }
 
232
 
 
233
        *last_refresh = (time_t)(((uint64_t)time_h << 32) + time_l);
 
234
        status = NT_STATUS_OK;
 
235
 
 
236
done:
 
237
        return status;
 
238
}
 
239
 
 
240
NTSTATUS printer_list_mark_reload(void)
 
241
{
 
242
        struct db_context *db;
 
243
        TDB_DATA data;
 
244
        uint32_t time_h, time_l;
 
245
        time_t now = time_mono(NULL);
 
246
        NTSTATUS status;
 
247
        int len;
 
248
 
 
249
        db = get_printer_list_db();
 
250
        if (db == NULL) {
 
251
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
252
        }
 
253
 
 
254
        time_l = ((uint64_t)now) & 0xFFFFFFFFL;
 
255
        time_h = ((uint64_t)now) >> 32;
 
256
 
 
257
        len = tdb_pack(NULL, 0, PL_TSTAMP_FORMAT, time_h, time_l);
 
258
 
 
259
        data.dptr = talloc_array(talloc_tos(), uint8_t, len);
 
260
        if (!data.dptr) {
 
261
                DEBUG(0, ("Failed to allocate tdb data buffer!\n"));
 
262
                status = NT_STATUS_NO_MEMORY;
 
263
                goto done;
 
264
        }
 
265
        data.dsize = len;
 
266
 
 
267
        len = tdb_pack(data.dptr, data.dsize,
 
268
                       PL_TSTAMP_FORMAT, time_h, time_l);
 
269
 
 
270
        status = dbwrap_store_bystring(db, PL_TIMESTAMP_KEY,
 
271
                                                data, TDB_REPLACE);
 
272
 
 
273
done:
 
274
        TALLOC_FREE(data.dptr);
 
275
        return status;
 
276
}
 
277
 
 
278
typedef int (printer_list_trv_fn_t)(struct db_record *, void *);
 
279
 
 
280
static NTSTATUS printer_list_traverse(printer_list_trv_fn_t *fn,
 
281
                                                void *private_data)
 
282
{
 
283
        struct db_context *db;
 
284
        int ret;
 
285
 
 
286
        db = get_printer_list_db();
 
287
        if (db == NULL) {
 
288
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
289
        }
 
290
 
 
291
        ret = db->traverse(db, fn, private_data);
 
292
        if (ret < 0) {
 
293
                return NT_STATUS_UNSUCCESSFUL;
 
294
        }
 
295
 
 
296
        return NT_STATUS_OK;
 
297
}
 
298
 
 
299
struct printer_list_clean_state {
 
300
        time_t last_refresh;
 
301
        NTSTATUS status;
 
302
};
 
303
 
 
304
static int printer_list_clean_fn(struct db_record *rec, void *private_data)
 
305
{
 
306
        struct printer_list_clean_state *state =
 
307
                        (struct printer_list_clean_state *)private_data;
 
308
        uint32_t time_h, time_l;
 
309
        time_t refresh;
 
310
        char *name;
 
311
        char *comment;
 
312
        char *location;
 
313
        int ret;
 
314
 
 
315
        /* skip anything that does not contain PL_DATA_FORMAT data */
 
316
        if (strncmp((char *)rec->key.dptr,
 
317
                    PL_KEY_PREFIX, sizeof(PL_KEY_PREFIX)-1)) {
 
318
                return 0;
 
319
        }
 
320
 
 
321
        ret = tdb_unpack(rec->value.dptr, rec->value.dsize,
 
322
                         PL_DATA_FORMAT, &time_h, &time_l, &name, &comment,
 
323
                         &location);
 
324
        if (ret == -1) {
 
325
                DEBUG(1, ("Failed to un pack printer data"));
 
326
                state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
 
327
                return -1;
 
328
        }
 
329
 
 
330
        SAFE_FREE(name);
 
331
        SAFE_FREE(comment);
 
332
        SAFE_FREE(location);
 
333
 
 
334
        refresh = (time_t)(((uint64_t)time_h << 32) + time_l);
 
335
 
 
336
        if (refresh < state->last_refresh) {
 
337
                state->status = rec->delete_rec(rec);
 
338
                if (!NT_STATUS_IS_OK(state->status)) {
 
339
                        return -1;
 
340
                }
 
341
        }
 
342
 
 
343
        return 0;
 
344
}
 
345
 
 
346
NTSTATUS printer_list_clean_old(void)
 
347
{
 
348
        struct printer_list_clean_state state;
 
349
        NTSTATUS status;
 
350
 
 
351
        status = printer_list_get_last_refresh(&state.last_refresh);
 
352
        if (!NT_STATUS_IS_OK(status)) {
 
353
                return status;
 
354
        }
 
355
 
 
356
        state.status = NT_STATUS_OK;
 
357
 
 
358
        status = printer_list_traverse(printer_list_clean_fn, &state);
 
359
        if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL) &&
 
360
            !NT_STATUS_IS_OK(state.status)) {
 
361
                status = state.status;
 
362
        }
 
363
 
 
364
        return status;
 
365
}
 
366
 
 
367
struct printer_list_exec_state {
 
368
        void (*fn)(const char *, const char *, const char *, void *);
 
369
        void *private_data;
 
370
        NTSTATUS status;
 
371
};
 
372
 
 
373
static int printer_list_exec_fn(struct db_record *rec, void *private_data)
 
374
{
 
375
        struct printer_list_exec_state *state =
 
376
                        (struct printer_list_exec_state *)private_data;
 
377
        uint32_t time_h, time_l;
 
378
        char *name;
 
379
        char *comment;
 
380
        char *location;
 
381
        int ret;
 
382
 
 
383
        /* always skip PL_TIMESTAMP_KEY key */
 
384
        if (strequal((const char *)rec->key.dptr, PL_TIMESTAMP_KEY)) {
 
385
                return 0;
 
386
        }
 
387
 
 
388
        ret = tdb_unpack(rec->value.dptr, rec->value.dsize,
 
389
                         PL_DATA_FORMAT, &time_h, &time_l, &name, &comment,
 
390
                         &location);
 
391
        if (ret == -1) {
 
392
                DEBUG(1, ("Failed to un pack printer data"));
 
393
                state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
 
394
                return -1;
 
395
        }
 
396
 
 
397
        state->fn(name, comment, location, state->private_data);
 
398
 
 
399
        SAFE_FREE(name);
 
400
        SAFE_FREE(comment);
 
401
        SAFE_FREE(location);
 
402
        return 0;
 
403
}
 
404
 
 
405
NTSTATUS printer_list_run_fn(void (*fn)(const char *, const char *, const char *, void *),
 
406
                             void *private_data)
 
407
{
 
408
        struct printer_list_exec_state state;
 
409
        NTSTATUS status;
 
410
 
 
411
        state.fn = fn;
 
412
        state.private_data = private_data;
 
413
        state.status = NT_STATUS_OK;
 
414
 
 
415
        status = printer_list_traverse(printer_list_exec_fn, &state);
 
416
        if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL) &&
 
417
            !NT_STATUS_IS_OK(state.status)) {
 
418
                status = state.status;
 
419
        }
 
420
 
 
421
        return status;
 
422
}