~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/modules/vfs_xattr_tdb.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Store posix-level xattrs in a tdb
 
3
 *
 
4
 * Copyright (C) Volker Lendecke, 2007
 
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 "librpc/gen_ndr/xattr.h"
 
22
#include "librpc/gen_ndr/ndr_xattr.h"
 
23
 
 
24
#undef DBGC_CLASS
 
25
#define DBGC_CLASS DBGC_VFS
 
26
 
 
27
/*
 
28
 * unmarshall tdb_xattrs
 
29
 */
 
30
 
 
31
static NTSTATUS xattr_tdb_pull_attrs(TALLOC_CTX *mem_ctx,
 
32
                                     const TDB_DATA *data,
 
33
                                     struct tdb_xattrs **presult)
 
34
{
 
35
        DATA_BLOB blob;
 
36
        enum ndr_err_code ndr_err;
 
37
        struct tdb_xattrs *result;
 
38
 
 
39
        if (!(result = TALLOC_ZERO_P(mem_ctx, struct tdb_xattrs))) {
 
40
                return NT_STATUS_NO_MEMORY;
 
41
        }
 
42
 
 
43
        if (data->dsize == 0) {
 
44
                *presult = result;
 
45
                return NT_STATUS_OK;
 
46
        }
 
47
 
 
48
        blob = data_blob_const(data->dptr, data->dsize);
 
49
 
 
50
        ndr_err = ndr_pull_struct_blob(
 
51
                &blob, result, NULL, result,
 
52
                (ndr_pull_flags_fn_t)ndr_pull_tdb_xattrs);
 
53
 
 
54
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
55
                DEBUG(0, ("ndr_pull_tdb_xattrs failed: %s\n",
 
56
                          ndr_errstr(ndr_err)));
 
57
                TALLOC_FREE(result);
 
58
                return ndr_map_error2ntstatus(ndr_err);;
 
59
        }
 
60
 
 
61
        *presult = result;
 
62
        return NT_STATUS_OK;
 
63
}
 
64
 
 
65
/*
 
66
 * marshall tdb_xattrs
 
67
 */
 
68
 
 
69
static NTSTATUS xattr_tdb_push_attrs(TALLOC_CTX *mem_ctx,
 
70
                                     const struct tdb_xattrs *attribs,
 
71
                                     TDB_DATA *data)
 
72
{
 
73
        DATA_BLOB blob;
 
74
        enum ndr_err_code ndr_err;
 
75
 
 
76
        ndr_err = ndr_push_struct_blob(
 
77
                &blob, mem_ctx, NULL, attribs,
 
78
                (ndr_push_flags_fn_t)ndr_push_tdb_xattrs);
 
79
 
 
80
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
81
                DEBUG(0, ("ndr_push_tdb_xattrs failed: %s\n",
 
82
                          ndr_errstr(ndr_err)));
 
83
                return ndr_map_error2ntstatus(ndr_err);;
 
84
        }
 
85
 
 
86
        *data = make_tdb_data(blob.data, blob.length);
 
87
        return NT_STATUS_OK;
 
88
}
 
89
 
 
90
/*
 
91
 * Load tdb_xattrs for a file from the tdb
 
92
 */
 
93
 
 
94
static NTSTATUS xattr_tdb_load_attrs(TALLOC_CTX *mem_ctx,
 
95
                                     struct db_context *db_ctx,
 
96
                                     const struct file_id *id,
 
97
                                     struct tdb_xattrs **presult)
 
98
{
 
99
        uint8 id_buf[16];
 
100
        NTSTATUS status;
 
101
        TDB_DATA data;
 
102
 
 
103
        /* For backwards compatibility only store the dev/inode. */
 
104
        push_file_id_16((char *)id_buf, id);
 
105
 
 
106
        if (db_ctx->fetch(db_ctx, mem_ctx,
 
107
                          make_tdb_data(id_buf, sizeof(id_buf)),
 
108
                          &data) == -1) {
 
109
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
110
        }
 
111
 
 
112
        status = xattr_tdb_pull_attrs(mem_ctx, &data, presult);
 
113
        TALLOC_FREE(data.dptr);
 
114
        return status;
 
115
}
 
116
 
 
117
/*
 
118
 * fetch_lock the tdb_ea record for a file
 
119
 */
 
120
 
 
121
static struct db_record *xattr_tdb_lock_attrs(TALLOC_CTX *mem_ctx,
 
122
                                              struct db_context *db_ctx,
 
123
                                              const struct file_id *id)
 
124
{
 
125
        uint8 id_buf[16];
 
126
 
 
127
        /* For backwards compatibility only store the dev/inode. */
 
128
        push_file_id_16((char *)id_buf, id);
 
129
        return db_ctx->fetch_locked(db_ctx, mem_ctx,
 
130
                                    make_tdb_data(id_buf, sizeof(id_buf)));
 
131
}
 
132
 
 
133
/*
 
134
 * Save tdb_xattrs to a previously fetch_locked record
 
135
 */
 
136
 
 
137
static NTSTATUS xattr_tdb_save_attrs(struct db_record *rec,
 
138
                                     const struct tdb_xattrs *attribs)
 
139
{
 
140
        TDB_DATA data = tdb_null;
 
141
        NTSTATUS status;
 
142
 
 
143
        status = xattr_tdb_push_attrs(talloc_tos(), attribs, &data);
 
144
 
 
145
        if (!NT_STATUS_IS_OK(status)) {
 
146
                DEBUG(0, ("xattr_tdb_push_attrs failed: %s\n",
 
147
                          nt_errstr(status)));
 
148
                return status;
 
149
        }
 
150
 
 
151
        status = rec->store(rec, data, 0);
 
152
 
 
153
        TALLOC_FREE(data.dptr);
 
154
 
 
155
        return status;
 
156
}
 
157
 
 
158
/*
 
159
 * Worker routine for getxattr and fgetxattr
 
160
 */
 
161
 
 
162
static ssize_t xattr_tdb_getattr(struct db_context *db_ctx,
 
163
                                 const struct file_id *id,
 
164
                                 const char *name, void *value, size_t size)
 
165
{
 
166
        struct tdb_xattrs *attribs;
 
167
        uint32_t i;
 
168
        ssize_t result = -1;
 
169
        NTSTATUS status;
 
170
 
 
171
        DEBUG(10, ("xattr_tdb_getattr called for file %s, name %s\n",
 
172
                   file_id_string_tos(id), name));
 
173
 
 
174
        status = xattr_tdb_load_attrs(talloc_tos(), db_ctx, id, &attribs);
 
175
 
 
176
        if (!NT_STATUS_IS_OK(status)) {
 
177
                DEBUG(10, ("xattr_tdb_fetch_attrs failed: %s\n",
 
178
                           nt_errstr(status)));
 
179
                errno = EINVAL;
 
180
                return -1;
 
181
        }
 
182
 
 
183
        for (i=0; i<attribs->num_eas; i++) {
 
184
                if (strcmp(attribs->eas[i].name, name) == 0) {
 
185
                        break;
 
186
                }
 
187
        }
 
188
 
 
189
        if (i == attribs->num_eas) {
 
190
                errno = ENOATTR;
 
191
                goto fail;
 
192
        }
 
193
 
 
194
        if (attribs->eas[i].value.length > size) {
 
195
                errno = ERANGE;
 
196
                goto fail;
 
197
        }
 
198
 
 
199
        memcpy(value, attribs->eas[i].value.data,
 
200
               attribs->eas[i].value.length);
 
201
        result = attribs->eas[i].value.length;
 
202
 
 
203
 fail:
 
204
        TALLOC_FREE(attribs);
 
205
        return result;
 
206
}
 
207
 
 
208
static ssize_t xattr_tdb_getxattr(struct vfs_handle_struct *handle,
 
209
                                  const char *path, const char *name,
 
210
                                  void *value, size_t size)
 
211
{
 
212
        SMB_STRUCT_STAT sbuf;
 
213
        struct file_id id;
 
214
        struct db_context *db;
 
215
        int ret;
 
216
 
 
217
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
218
 
 
219
        if (lp_posix_pathnames()) {
 
220
                ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
 
221
        } else {
 
222
                ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
 
223
        }
 
224
 
 
225
        if (ret == -1) {
 
226
                return -1;
 
227
        }
 
228
 
 
229
        id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
230
 
 
231
        return xattr_tdb_getattr(db, &id, name, value, size);
 
232
}
 
233
 
 
234
static ssize_t xattr_tdb_fgetxattr(struct vfs_handle_struct *handle,
 
235
                                   struct files_struct *fsp,
 
236
                                   const char *name, void *value, size_t size)
 
237
{
 
238
        SMB_STRUCT_STAT sbuf;
 
239
        struct file_id id;
 
240
        struct db_context *db;
 
241
 
 
242
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
243
 
 
244
        if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
 
245
                return -1;
 
246
        }
 
247
 
 
248
        id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
249
 
 
250
        return xattr_tdb_getattr(db, &id, name, value, size);
 
251
}
 
252
 
 
253
/*
 
254
 * Worker routine for setxattr and fsetxattr
 
255
 */
 
256
 
 
257
static int xattr_tdb_setattr(struct db_context *db_ctx,
 
258
                             const struct file_id *id, const char *name,
 
259
                             const void *value, size_t size, int flags)
 
260
{
 
261
        NTSTATUS status;
 
262
        struct db_record *rec;
 
263
        struct tdb_xattrs *attribs;
 
264
        uint32_t i;
 
265
 
 
266
        DEBUG(10, ("xattr_tdb_setattr called for file %s, name %s\n",
 
267
                   file_id_string_tos(id), name));
 
268
 
 
269
        rec = xattr_tdb_lock_attrs(talloc_tos(), db_ctx, id);
 
270
 
 
271
        if (rec == NULL) {
 
272
                DEBUG(0, ("xattr_tdb_lock_attrs failed\n"));
 
273
                errno = EINVAL;
 
274
                return -1;
 
275
        }
 
276
 
 
277
        status = xattr_tdb_pull_attrs(rec, &rec->value, &attribs);
 
278
 
 
279
        if (!NT_STATUS_IS_OK(status)) {
 
280
                DEBUG(10, ("xattr_tdb_fetch_attrs failed: %s\n",
 
281
                           nt_errstr(status)));
 
282
                TALLOC_FREE(rec);
 
283
                return -1;
 
284
        }
 
285
 
 
286
        for (i=0; i<attribs->num_eas; i++) {
 
287
                if (strcmp(attribs->eas[i].name, name) == 0) {
 
288
                        if (flags & XATTR_CREATE) {
 
289
                                TALLOC_FREE(rec);
 
290
                                errno = EEXIST;
 
291
                                return -1;
 
292
                        }
 
293
                        break;
 
294
                }
 
295
        }
 
296
 
 
297
        if (i == attribs->num_eas) {
 
298
                struct xattr_EA *tmp;
 
299
 
 
300
                if (flags & XATTR_REPLACE) {
 
301
                        TALLOC_FREE(rec);
 
302
                        errno = ENOATTR;
 
303
                        return -1;
 
304
                }
 
305
 
 
306
                tmp = TALLOC_REALLOC_ARRAY(
 
307
                        attribs, attribs->eas, struct xattr_EA,
 
308
                        attribs->num_eas+ 1);
 
309
 
 
310
                if (tmp == NULL) {
 
311
                        DEBUG(0, ("TALLOC_REALLOC_ARRAY failed\n"));
 
312
                        TALLOC_FREE(rec);
 
313
                        errno = ENOMEM;
 
314
                        return -1;
 
315
                }
 
316
 
 
317
                attribs->eas = tmp;
 
318
                attribs->num_eas += 1;
 
319
        }
 
320
 
 
321
        attribs->eas[i].name = name;
 
322
        attribs->eas[i].value.data = CONST_DISCARD(uint8 *, value);
 
323
        attribs->eas[i].value.length = size;
 
324
 
 
325
        status = xattr_tdb_save_attrs(rec, attribs);
 
326
 
 
327
        TALLOC_FREE(rec);
 
328
 
 
329
        if (!NT_STATUS_IS_OK(status)) {
 
330
                DEBUG(1, ("save failed: %s\n", nt_errstr(status)));
 
331
                return -1;
 
332
        }
 
333
 
 
334
        return 0;
 
335
}
 
336
 
 
337
static int xattr_tdb_setxattr(struct vfs_handle_struct *handle,
 
338
                              const char *path, const char *name,
 
339
                              const void *value, size_t size, int flags)
 
340
{
 
341
        SMB_STRUCT_STAT sbuf;
 
342
        struct file_id id;
 
343
        struct db_context *db;
 
344
        int ret;
 
345
 
 
346
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
347
 
 
348
        if (lp_posix_pathnames()) {
 
349
                ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
 
350
        } else {
 
351
                ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
 
352
        }
 
353
 
 
354
        if (ret == -1) {
 
355
                return -1;
 
356
        }
 
357
 
 
358
        id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
359
 
 
360
        return xattr_tdb_setattr(db, &id, name, value, size, flags);
 
361
}
 
362
 
 
363
static int xattr_tdb_fsetxattr(struct vfs_handle_struct *handle,
 
364
                               struct files_struct *fsp,
 
365
                               const char *name, const void *value,
 
366
                               size_t size, int flags)
 
367
{
 
368
        SMB_STRUCT_STAT sbuf;
 
369
        struct file_id id;
 
370
        struct db_context *db;
 
371
 
 
372
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
373
 
 
374
        if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
 
375
                return -1;
 
376
        }
 
377
 
 
378
        id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
379
 
 
380
        return xattr_tdb_setattr(db, &id, name, value, size, flags);
 
381
}
 
382
 
 
383
/*
 
384
 * Worker routine for listxattr and flistxattr
 
385
 */
 
386
 
 
387
static ssize_t xattr_tdb_listattr(struct db_context *db_ctx,
 
388
                                  const struct file_id *id, char *list,
 
389
                                  size_t size)
 
390
{
 
391
        NTSTATUS status;
 
392
        struct tdb_xattrs *attribs;
 
393
        uint32_t i;
 
394
        size_t len = 0;
 
395
 
 
396
        status = xattr_tdb_load_attrs(talloc_tos(), db_ctx, id, &attribs);
 
397
 
 
398
        if (!NT_STATUS_IS_OK(status)) {
 
399
                DEBUG(10, ("xattr_tdb_fetch_attrs failed: %s\n",
 
400
                           nt_errstr(status)));
 
401
                errno = EINVAL;
 
402
                return -1;
 
403
        }
 
404
 
 
405
        DEBUG(10, ("xattr_tdb_listattr: Found %d xattrs\n",
 
406
                   attribs->num_eas));
 
407
 
 
408
        for (i=0; i<attribs->num_eas; i++) {
 
409
                size_t tmp;
 
410
 
 
411
                DEBUG(10, ("xattr_tdb_listattr: xattrs[i].name: %s\n",
 
412
                           attribs->eas[i].name));
 
413
 
 
414
                tmp = strlen(attribs->eas[i].name);
 
415
 
 
416
                /*
 
417
                 * Try to protect against overflow
 
418
                 */
 
419
 
 
420
                if (len + (tmp+1) < len) {
 
421
                        TALLOC_FREE(attribs);
 
422
                        errno = EINVAL;
 
423
                        return -1;
 
424
                }
 
425
 
 
426
                /*
 
427
                 * Take care of the terminating NULL
 
428
                 */
 
429
                len += (tmp + 1);
 
430
        }
 
431
 
 
432
        if (len > size) {
 
433
                TALLOC_FREE(attribs);
 
434
                errno = ERANGE;
 
435
                return -1;
 
436
        }
 
437
 
 
438
        len = 0;
 
439
 
 
440
        for (i=0; i<attribs->num_eas; i++) {
 
441
                strlcpy(list+len, attribs->eas[i].name,
 
442
                        size-len);
 
443
                len += (strlen(attribs->eas[i].name) + 1);
 
444
        }
 
445
 
 
446
        TALLOC_FREE(attribs);
 
447
        return len;
 
448
}
 
449
 
 
450
static ssize_t xattr_tdb_listxattr(struct vfs_handle_struct *handle,
 
451
                                   const char *path, char *list, size_t size)
 
452
{
 
453
        SMB_STRUCT_STAT sbuf;
 
454
        struct file_id id;
 
455
        struct db_context *db;
 
456
        int ret;
 
457
 
 
458
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
459
 
 
460
        if (lp_posix_pathnames()) {
 
461
                ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
 
462
        } else {
 
463
                ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
 
464
        }
 
465
 
 
466
        if (ret == -1) {
 
467
                return -1;
 
468
        }
 
469
 
 
470
        id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
471
 
 
472
        return xattr_tdb_listattr(db, &id, list, size);
 
473
}
 
474
 
 
475
static ssize_t xattr_tdb_flistxattr(struct vfs_handle_struct *handle,
 
476
                                    struct files_struct *fsp, char *list,
 
477
                                    size_t size)
 
478
{
 
479
        SMB_STRUCT_STAT sbuf;
 
480
        struct file_id id;
 
481
        struct db_context *db;
 
482
 
 
483
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
484
 
 
485
        if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
 
486
                return -1;
 
487
        }
 
488
 
 
489
        id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
490
 
 
491
        return xattr_tdb_listattr(db, &id, list, size);
 
492
}
 
493
 
 
494
/*
 
495
 * Worker routine for removexattr and fremovexattr
 
496
 */
 
497
 
 
498
static int xattr_tdb_removeattr(struct db_context *db_ctx,
 
499
                                const struct file_id *id, const char *name)
 
500
{
 
501
        NTSTATUS status;
 
502
        struct db_record *rec;
 
503
        struct tdb_xattrs *attribs;
 
504
        uint32_t i;
 
505
 
 
506
        rec = xattr_tdb_lock_attrs(talloc_tos(), db_ctx, id);
 
507
 
 
508
        if (rec == NULL) {
 
509
                DEBUG(0, ("xattr_tdb_lock_attrs failed\n"));
 
510
                errno = EINVAL;
 
511
                return -1;
 
512
        }
 
513
 
 
514
        status = xattr_tdb_pull_attrs(rec, &rec->value, &attribs);
 
515
 
 
516
        if (!NT_STATUS_IS_OK(status)) {
 
517
                DEBUG(10, ("xattr_tdb_fetch_attrs failed: %s\n",
 
518
                           nt_errstr(status)));
 
519
                TALLOC_FREE(rec);
 
520
                return -1;
 
521
        }
 
522
 
 
523
        for (i=0; i<attribs->num_eas; i++) {
 
524
                if (strcmp(attribs->eas[i].name, name) == 0) {
 
525
                        break;
 
526
                }
 
527
        }
 
528
 
 
529
        if (i == attribs->num_eas) {
 
530
                TALLOC_FREE(rec);
 
531
                errno = ENOATTR;
 
532
                return -1;
 
533
        }
 
534
 
 
535
        attribs->eas[i] =
 
536
                attribs->eas[attribs->num_eas-1];
 
537
        attribs->num_eas -= 1;
 
538
 
 
539
        if (attribs->num_eas == 0) {
 
540
                rec->delete_rec(rec);
 
541
                TALLOC_FREE(rec);
 
542
                return 0;
 
543
        }
 
544
 
 
545
        status = xattr_tdb_save_attrs(rec, attribs);
 
546
 
 
547
        TALLOC_FREE(rec);
 
548
 
 
549
        if (!NT_STATUS_IS_OK(status)) {
 
550
                DEBUG(1, ("save failed: %s\n", nt_errstr(status)));
 
551
                return -1;
 
552
        }
 
553
 
 
554
        return 0;
 
555
}
 
556
 
 
557
static int xattr_tdb_removexattr(struct vfs_handle_struct *handle,
 
558
                                 const char *path, const char *name)
 
559
{
 
560
        SMB_STRUCT_STAT sbuf;
 
561
        struct file_id id;
 
562
        struct db_context *db;
 
563
        int ret;
 
564
 
 
565
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
566
 
 
567
        if (lp_posix_pathnames()) {
 
568
                ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
 
569
        } else {
 
570
                ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
 
571
        }
 
572
 
 
573
        if (ret == -1) {
 
574
                return -1;
 
575
        }
 
576
 
 
577
        id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
578
 
 
579
        return xattr_tdb_removeattr(db, &id, name);
 
580
}
 
581
 
 
582
static int xattr_tdb_fremovexattr(struct vfs_handle_struct *handle,
 
583
                                  struct files_struct *fsp, const char *name)
 
584
{
 
585
        SMB_STRUCT_STAT sbuf;
 
586
        struct file_id id;
 
587
        struct db_context *db;
 
588
 
 
589
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
590
 
 
591
        if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
 
592
                return -1;
 
593
        }
 
594
 
 
595
        id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
596
 
 
597
        return xattr_tdb_removeattr(db, &id, name);
 
598
}
 
599
 
 
600
/*
 
601
 * Open the tdb file upon VFS_CONNECT
 
602
 */
 
603
 
 
604
static bool xattr_tdb_init(int snum, struct db_context **p_db)
 
605
{
 
606
        struct db_context *db;
 
607
        const char *dbname;
 
608
        char *def_dbname;
 
609
 
 
610
        def_dbname = state_path("xattr.tdb");
 
611
        if (def_dbname == NULL) {
 
612
                errno = ENOSYS;
 
613
                return false;
 
614
        }
 
615
 
 
616
        dbname = lp_parm_const_string(snum, "xattr_tdb", "file", def_dbname);
 
617
 
 
618
        /* now we know dbname is not NULL */
 
619
 
 
620
        become_root();
 
621
        db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
 
622
        unbecome_root();
 
623
 
 
624
        if (db == NULL) {
 
625
#if defined(ENOTSUP)
 
626
                errno = ENOTSUP;
 
627
#else
 
628
                errno = ENOSYS;
 
629
#endif
 
630
                TALLOC_FREE(def_dbname);
 
631
                return false;
 
632
        }
 
633
 
 
634
        *p_db = db;
 
635
        TALLOC_FREE(def_dbname);
 
636
        return true;
 
637
}
 
638
 
 
639
/*
 
640
 * On unlink we need to delete the tdb record
 
641
 */
 
642
static int xattr_tdb_unlink(vfs_handle_struct *handle, const char *path)
 
643
{
 
644
        SMB_STRUCT_STAT sbuf;
 
645
        struct file_id id;
 
646
        struct db_context *db;
 
647
        struct db_record *rec;
 
648
        int ret;
 
649
 
 
650
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
651
 
 
652
        if (lp_posix_pathnames()) {
 
653
                ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
 
654
        } else {
 
655
                ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
 
656
        }
 
657
 
 
658
        if (ret == -1) {
 
659
                return -1;
 
660
        }
 
661
 
 
662
        ret = SMB_VFS_NEXT_UNLINK(handle, path);
 
663
 
 
664
        if (ret == -1) {
 
665
                return -1;
 
666
        }
 
667
 
 
668
        id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
669
 
 
670
        rec = xattr_tdb_lock_attrs(talloc_tos(), db, &id);
 
671
 
 
672
        /*
 
673
         * If rec == NULL there's not much we can do about it
 
674
         */
 
675
 
 
676
        if (rec != NULL) {
 
677
                rec->delete_rec(rec);
 
678
                TALLOC_FREE(rec);
 
679
        }
 
680
 
 
681
        return 0;
 
682
}
 
683
 
 
684
/*
 
685
 * On rmdir we need to delete the tdb record
 
686
 */
 
687
static int xattr_tdb_rmdir(vfs_handle_struct *handle, const char *path)
 
688
{
 
689
        SMB_STRUCT_STAT sbuf;
 
690
        struct file_id id;
 
691
        struct db_context *db;
 
692
        struct db_record *rec;
 
693
        int ret;
 
694
 
 
695
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
696
 
 
697
        if (lp_posix_pathnames()) {
 
698
                ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
 
699
        } else {
 
700
                ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
 
701
        }
 
702
 
 
703
        if (ret == -1) {
 
704
                return -1;
 
705
        }
 
706
 
 
707
        ret = SMB_VFS_NEXT_RMDIR(handle, path);
 
708
 
 
709
        if (ret == -1) {
 
710
                return -1;
 
711
        }
 
712
 
 
713
        id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
714
 
 
715
        rec = xattr_tdb_lock_attrs(talloc_tos(), db, &id);
 
716
 
 
717
        /*
 
718
         * If rec == NULL there's not much we can do about it
 
719
         */
 
720
 
 
721
        if (rec != NULL) {
 
722
                rec->delete_rec(rec);
 
723
                TALLOC_FREE(rec);
 
724
        }
 
725
 
 
726
        return 0;
 
727
}
 
728
 
 
729
/*
 
730
 * Destructor for the VFS private data
 
731
 */
 
732
 
 
733
static void close_xattr_db(void **data)
 
734
{
 
735
        struct db_context **p_db = (struct db_context **)data;
 
736
        TALLOC_FREE(*p_db);
 
737
}
 
738
 
 
739
static int xattr_tdb_connect(vfs_handle_struct *handle, const char *service,
 
740
                          const char *user)
 
741
{
 
742
        fstring sname;
 
743
        int res, snum;
 
744
        struct db_context *db;
 
745
 
 
746
        res = SMB_VFS_NEXT_CONNECT(handle, service, user);
 
747
        if (res < 0) {
 
748
                return res;
 
749
        }
 
750
 
 
751
        fstrcpy(sname, service);
 
752
        snum = find_service(sname);
 
753
        if (snum == -1) {
 
754
                /*
 
755
                 * Should not happen, but we should not fail just *here*.
 
756
                 */
 
757
                return 0;
 
758
        }
 
759
 
 
760
        if (!xattr_tdb_init(snum, &db)) {
 
761
                DEBUG(5, ("Could not init xattr tdb\n"));
 
762
                lp_do_parameter(snum, "ea support", "False");
 
763
                return 0;
 
764
        }
 
765
 
 
766
        lp_do_parameter(snum, "ea support", "True");
 
767
 
 
768
        SMB_VFS_HANDLE_SET_DATA(handle, db, close_xattr_db,
 
769
                                struct db_context, return -1);
 
770
 
 
771
        return 0;
 
772
}
 
773
 
 
774
/* VFS operations structure */
 
775
 
 
776
static const vfs_op_tuple xattr_tdb_ops[] = {
 
777
        {SMB_VFS_OP(xattr_tdb_getxattr), SMB_VFS_OP_GETXATTR,
 
778
         SMB_VFS_LAYER_TRANSPARENT},
 
779
        {SMB_VFS_OP(xattr_tdb_fgetxattr), SMB_VFS_OP_FGETXATTR,
 
780
         SMB_VFS_LAYER_TRANSPARENT},
 
781
        {SMB_VFS_OP(xattr_tdb_setxattr), SMB_VFS_OP_SETXATTR,
 
782
         SMB_VFS_LAYER_TRANSPARENT},
 
783
        {SMB_VFS_OP(xattr_tdb_fsetxattr), SMB_VFS_OP_FSETXATTR,
 
784
         SMB_VFS_LAYER_TRANSPARENT},
 
785
        {SMB_VFS_OP(xattr_tdb_listxattr), SMB_VFS_OP_LISTXATTR,
 
786
         SMB_VFS_LAYER_TRANSPARENT},
 
787
        {SMB_VFS_OP(xattr_tdb_flistxattr), SMB_VFS_OP_FLISTXATTR,
 
788
         SMB_VFS_LAYER_TRANSPARENT},
 
789
        {SMB_VFS_OP(xattr_tdb_removexattr), SMB_VFS_OP_REMOVEXATTR,
 
790
         SMB_VFS_LAYER_TRANSPARENT},
 
791
        {SMB_VFS_OP(xattr_tdb_fremovexattr), SMB_VFS_OP_FREMOVEXATTR,
 
792
         SMB_VFS_LAYER_TRANSPARENT},
 
793
        {SMB_VFS_OP(xattr_tdb_unlink), SMB_VFS_OP_UNLINK,
 
794
         SMB_VFS_LAYER_TRANSPARENT},
 
795
        {SMB_VFS_OP(xattr_tdb_rmdir), SMB_VFS_OP_RMDIR,
 
796
         SMB_VFS_LAYER_TRANSPARENT},
 
797
        {SMB_VFS_OP(xattr_tdb_connect), SMB_VFS_OP_CONNECT,
 
798
         SMB_VFS_LAYER_TRANSPARENT},
 
799
        {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
 
800
};
 
801
 
 
802
NTSTATUS vfs_xattr_tdb_init(void);
 
803
NTSTATUS vfs_xattr_tdb_init(void)
 
804
{
 
805
        return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "xattr_tdb",
 
806
                                xattr_tdb_ops);
 
807
}