~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/lib/sysacls.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
   Unix SMB/CIFS implementation.
 
3
   Samba system utilities for ACL support.
 
4
   Copyright (C) Jeremy Allison 2000.
 
5
   Copyright (C) Volker Lendecke 2006
 
6
   Copyright (C) Michael Adam 2006,2008
 
7
   
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 3 of the License, or
 
11
   (at your option) any later version.
 
12
   
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
   
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
*/
 
21
 
 
22
#include "includes.h"
 
23
 
 
24
#undef  DBGC_CLASS
 
25
#define DBGC_CLASS DBGC_ACLS
 
26
 
 
27
/*
 
28
 * Note that while this code implements sufficient functionality
 
29
 * to support the sys_acl_* interfaces it does not provide all
 
30
 * of the semantics of the POSIX ACL interfaces.
 
31
 *
 
32
 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
 
33
 * from a call to sys_acl_get_entry() should not be assumed to be
 
34
 * valid after calling any of the following functions, which may
 
35
 * reorder the entries in the ACL.
 
36
 *
 
37
 *      sys_acl_valid()
 
38
 *      sys_acl_set_file()
 
39
 *      sys_acl_set_fd()
 
40
 */
 
41
 
 
42
int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
 
43
{
 
44
        if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
 
45
                errno = EINVAL;
 
46
                return -1;
 
47
        }
 
48
 
 
49
        if (entry_p == NULL) {
 
50
                errno = EINVAL;
 
51
                return -1;
 
52
        }
 
53
 
 
54
        if (entry_id == SMB_ACL_FIRST_ENTRY) {
 
55
                acl_d->next = 0;
 
56
        }
 
57
 
 
58
        if (acl_d->next < 0) {
 
59
                errno = EINVAL;
 
60
                return -1;
 
61
        }
 
62
 
 
63
        if (acl_d->next >= acl_d->count) {
 
64
                return 0;
 
65
        }
 
66
 
 
67
        *entry_p = &acl_d->acl[acl_d->next++];
 
68
 
 
69
        return 1;
 
70
}
 
71
 
 
72
int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
 
73
{
 
74
        *type_p = entry_d->a_type;
 
75
 
 
76
        return 0;
 
77
}
 
78
 
 
79
int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
 
80
{
 
81
        *permset_p = &entry_d->a_perm;
 
82
 
 
83
        return 0;
 
84
}
 
85
 
 
86
void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
 
87
{
 
88
        if (entry_d->a_type == SMB_ACL_USER) {
 
89
                return &entry_d->uid;
 
90
                }
 
91
 
 
92
        if (entry_d->a_type == SMB_ACL_GROUP) {
 
93
                return &entry_d->gid;
 
94
        }
 
95
 
 
96
        errno = EINVAL;
 
97
                return NULL;
 
98
}
 
99
 
 
100
int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
 
101
{
 
102
        *permset_d = 0;
 
103
 
 
104
        return 0;
 
105
}
 
106
 
 
107
int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
 
108
{
 
109
        if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
 
110
            && perm != SMB_ACL_EXECUTE) {
 
111
                errno = EINVAL;
 
112
                return -1;
 
113
                }
 
114
 
 
115
        if (permset_d == NULL) {
 
116
                errno = EINVAL;
 
117
                return -1;
 
118
        }
 
119
 
 
120
        *permset_d |= perm;
 
121
 
 
122
        return 0;
 
123
}
 
124
 
 
125
int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
 
126
{
 
127
        return *permset_d & perm;
 
128
}
 
129
 
 
130
char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
 
131
{
 
132
        int     i;
 
133
        int     len, maxlen;
 
134
        char    *text;
 
135
 
 
136
        /*
 
137
         * use an initial estimate of 20 bytes per ACL entry
 
138
         * when allocating memory for the text representation
 
139
         * of the ACL
 
140
         */
 
141
        len     = 0;
 
142
        maxlen  = 20 * acl_d->count;
 
143
        if ((text = (char *)SMB_MALLOC(maxlen)) == NULL) {
 
144
                errno = ENOMEM;
 
145
                return NULL;
 
146
        }
 
147
 
 
148
        for (i = 0; i < acl_d->count; i++) {
 
149
                struct smb_acl_entry *ap = &acl_d->acl[i];
 
150
                struct group    *gr;
 
151
                char            tagbuf[12];
 
152
                char            idbuf[12];
 
153
                const char      *tag;
 
154
                const char      *id     = "";
 
155
                char            perms[4];
 
156
                int             nbytes;
 
157
 
 
158
                switch (ap->a_type) {
 
159
                        /*
 
160
                         * for debugging purposes it's probably more
 
161
                         * useful to dump unknown tag types rather
 
162
                         * than just returning an error
 
163
                         */
 
164
                        default:
 
165
                                slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
 
166
                                         ap->a_type);
 
167
                                tag = tagbuf;
 
168
                                break;
 
169
 
 
170
                        case SMB_ACL_USER:
 
171
                                id = uidtoname(ap->uid);
 
172
                        case SMB_ACL_USER_OBJ:
 
173
                                tag = "user";
 
174
                                break;
 
175
 
 
176
                        case SMB_ACL_GROUP:
 
177
                                if ((gr = getgrgid(ap->gid)) == NULL) {
 
178
                                        slprintf(idbuf, sizeof(idbuf)-1, "%ld",
 
179
                                                (long)ap->gid);
 
180
                                        id = idbuf;
 
181
                                } else {
 
182
                                        id = gr->gr_name;
 
183
                                }
 
184
                        case SMB_ACL_GROUP_OBJ:
 
185
                                tag = "group";
 
186
                                break;
 
187
 
 
188
                        case SMB_ACL_OTHER:
 
189
                                tag = "other";
 
190
                                break;
 
191
 
 
192
                        case SMB_ACL_MASK:
 
193
                                tag = "mask";
 
194
                                break;
 
195
 
 
196
                }
 
197
 
 
198
                perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
 
199
                perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
 
200
                perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
 
201
                perms[3] = '\0';
 
202
 
 
203
                /*          <tag>      :  <qualifier>   :  rwx \n  \0 */
 
204
                nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
 
205
 
 
206
                /*
 
207
                 * If this entry would overflow the buffer
 
208
                 * allocate enough additional memory for this
 
209
                 * entry and an estimate of another 20 bytes
 
210
                 * for each entry still to be processed
 
211
                 */
 
212
                if ((len + nbytes) > maxlen) {
 
213
                        maxlen += nbytes + 20 * (acl_d->count - i);
 
214
                        if ((text = (char *)SMB_REALLOC(text, maxlen)) == NULL) {
 
215
                        errno = ENOMEM;
 
216
                                return NULL;
 
217
                }
 
218
        }
 
219
 
 
220
                slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
 
221
                len += nbytes - 1;
 
222
        }
 
223
 
 
224
        if (len_p)
 
225
                *len_p = len;
 
226
 
 
227
        return text;
 
228
}
 
229
 
 
230
SMB_ACL_T sys_acl_init(int count)
 
231
{
 
232
        SMB_ACL_T       a;
 
233
 
 
234
        if (count < 0) {
 
235
                errno = EINVAL;
 
236
                return NULL;
 
237
        }
 
238
 
 
239
        /*
 
240
         * note that since the definition of the structure pointed
 
241
         * to by the SMB_ACL_T includes the first element of the
 
242
         * acl[] array, this actually allocates an ACL with room
 
243
         * for (count+1) entries
 
244
         */
 
245
        if ((a = (struct smb_acl_t *)SMB_MALLOC(
 
246
                     sizeof(struct smb_acl_t) +
 
247
                     count * sizeof(struct smb_acl_entry))) == NULL) {
 
248
                errno = ENOMEM;
 
249
                return NULL;
 
250
        }
 
251
 
 
252
        a->size = count + 1;
 
253
        a->count = 0;
 
254
        a->next = -1;
 
255
 
 
256
        return a;
 
257
}
 
258
 
 
259
int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
 
260
{
 
261
        SMB_ACL_T       acl_d;
 
262
        SMB_ACL_ENTRY_T entry_d;
 
263
 
 
264
        if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
 
265
                errno = EINVAL;
 
266
                return -1;
 
267
        }
 
268
 
 
269
        if (acl_d->count >= acl_d->size) {
 
270
                errno = ENOSPC;
 
271
                return -1;
 
272
        }
 
273
 
 
274
        entry_d         = &acl_d->acl[acl_d->count++];
 
275
        entry_d->a_type = SMB_ACL_TAG_INVALID;
 
276
        entry_d->uid    = -1;
 
277
        entry_d->gid    = -1;
 
278
        entry_d->a_perm = 0;
 
279
        *entry_p        = entry_d;
 
280
 
 
281
        return 0;
 
282
}
 
283
 
 
284
int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
 
285
{
 
286
        switch (tag_type) {
 
287
                case SMB_ACL_USER:
 
288
                case SMB_ACL_USER_OBJ:
 
289
                case SMB_ACL_GROUP:
 
290
                case SMB_ACL_GROUP_OBJ:
 
291
                case SMB_ACL_OTHER:
 
292
                case SMB_ACL_MASK:
 
293
                        entry_d->a_type = tag_type;
 
294
                        break;
 
295
                default:
 
296
                        errno = EINVAL;
 
297
                        return -1;
 
298
                }
 
299
 
 
300
        return 0;
 
301
}
 
302
 
 
303
int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
 
304
{
 
305
        if (entry_d->a_type == SMB_ACL_USER) {
 
306
                entry_d->uid = *((uid_t *)qual_p);
 
307
                return 0;
 
308
                }
 
309
        if (entry_d->a_type == SMB_ACL_GROUP) {
 
310
                entry_d->gid = *((gid_t *)qual_p);
 
311
                return 0;
 
312
        }
 
313
 
 
314
        errno = EINVAL;
 
315
        return -1;
 
316
}
 
317
 
 
318
int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
 
319
{
 
320
        if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
 
321
                errno = EINVAL;
 
322
                return -1;
 
323
        }
 
324
 
 
325
        entry_d->a_perm = *permset_d;
 
326
 
 
327
        return 0;
 
328
}
 
329
 
 
330
int sys_acl_free_text(char *text)
 
331
{
 
332
        SAFE_FREE(text);
 
333
        return 0;
 
334
}
 
335
 
 
336
int sys_acl_free_acl(SMB_ACL_T acl_d) 
 
337
{
 
338
        SAFE_FREE(acl_d);
 
339
        return 0;
 
340
}
 
341
 
 
342
int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
 
343
{
 
344
        return 0;
 
345
}
 
346
 
 
347
int sys_acl_valid(SMB_ACL_T acl_d)
 
348
{
 
349
        errno = EINVAL;
 
350
        return -1;
 
351
}
 
352
 
 
353
/*
 
354
 * acl_get_file, acl_get_fd, acl_set_file, acl_set_fd and
 
355
 * sys_acl_delete_def_file are to be redirected to the default
 
356
 * statically-bound acl vfs module, but they are replacable.
 
357
 */
 
358
 
 
359
#if defined(HAVE_POSIX_ACLS)
 
360
 
 
361
SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle, 
 
362
                           const char *path_p, SMB_ACL_TYPE_T type)
 
363
{
 
364
        return posixacl_sys_acl_get_file(handle, path_p, type);
 
365
}
 
366
 
 
367
SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
 
368
{
 
369
        return posixacl_sys_acl_get_fd(handle, fsp);
 
370
}
 
371
 
 
372
int sys_acl_set_file(vfs_handle_struct *handle,
 
373
                     const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
 
374
{
 
375
        return posixacl_sys_acl_set_file(handle, name, type, acl_d);
 
376
}
 
377
 
 
378
int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
 
379
                   SMB_ACL_T acl_d)
 
380
{
 
381
        return posixacl_sys_acl_set_fd(handle, fsp, acl_d);
 
382
}
 
383
 
 
384
int sys_acl_delete_def_file(vfs_handle_struct *handle,
 
385
                            const char *path)
 
386
{
 
387
        return posixacl_sys_acl_delete_def_file(handle, path);
 
388
}
 
389
 
 
390
#elif defined(HAVE_AIX_ACLS)
 
391
 
 
392
SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
 
393
                           const char *path_p, SMB_ACL_TYPE_T type)
 
394
{
 
395
        return aixacl_sys_acl_get_file(handle, path_p, type);
 
396
}
 
397
 
 
398
SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
 
399
{
 
400
        return aixacl_sys_acl_get_fd(handle, fsp);
 
401
}
 
402
 
 
403
int sys_acl_set_file(vfs_handle_struct *handle,
 
404
                     const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
 
405
{
 
406
        return aixacl_sys_acl_set_file(handle, name, type, acl_d);
 
407
}
 
408
 
 
409
int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
 
410
                   SMB_ACL_T acl_d)
 
411
{
 
412
        return aixacl_sys_acl_set_fd(handle, fsp, acl_d);
 
413
}
 
414
 
 
415
int sys_acl_delete_def_file(vfs_handle_struct *handle,
 
416
                            const char *path)
 
417
{
 
418
        return aixacl_sys_acl_delete_def_file(handle, path);
 
419
}
 
420
 
 
421
#elif defined(HAVE_TRU64_ACLS)
 
422
 
 
423
SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
 
424
                           const char *path_p, SMB_ACL_TYPE_T type)
 
425
{
 
426
        return tru64acl_sys_acl_get_file(handle, path_p, type);
 
427
}
 
428
 
 
429
SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
 
430
{
 
431
        return tru64acl_sys_acl_get_fd(handle, fsp);
 
432
}
 
433
 
 
434
int sys_acl_set_file(vfs_handle_struct *handle,
 
435
                     const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
 
436
{
 
437
        return tru64acl_sys_acl_set_file(handle, name, type, acl_d);
 
438
}
 
439
 
 
440
int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
 
441
                   SMB_ACL_T acl_d)
 
442
{
 
443
        return tru64acl_sys_acl_set_fd(handle, fsp, acl_d);
 
444
}
 
445
 
 
446
int sys_acl_delete_def_file(vfs_handle_struct *handle,
 
447
                            const char *path)
 
448
{
 
449
        return tru64acl_sys_acl_delete_def_file(handle, path);
 
450
}
 
451
 
 
452
#elif defined(HAVE_SOLARIS_ACLS) || defined(HAVE_UNIXWARE_ACLS)
 
453
 
 
454
SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
 
455
                           const char *path_p, SMB_ACL_TYPE_T type)
 
456
{
 
457
        return solarisacl_sys_acl_get_file(handle, path_p, type);
 
458
}
 
459
 
 
460
SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
 
461
{
 
462
        return solarisacl_sys_acl_get_fd(handle, fsp);
 
463
}
 
464
 
 
465
int sys_acl_set_file(vfs_handle_struct *handle,
 
466
                     const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
 
467
{
 
468
        return solarisacl_sys_acl_set_file(handle, name, type, acl_d);
 
469
}
 
470
 
 
471
int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
 
472
                   SMB_ACL_T acl_d)
 
473
{
 
474
        return solarisacl_sys_acl_set_fd(handle, fsp, acl_d);
 
475
}
 
476
 
 
477
int sys_acl_delete_def_file(vfs_handle_struct *handle,
 
478
                            const char *path)
 
479
{
 
480
        return solarisacl_sys_acl_delete_def_file(handle, path);
 
481
}
 
482
 
 
483
#elif defined(HAVE_HPUX_ACLS)
 
484
 
 
485
SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
 
486
                           const char *path_p, SMB_ACL_TYPE_T type)
 
487
{
 
488
        return hpuxacl_sys_acl_get_file(handle, path_p, type);
 
489
}
 
490
 
 
491
SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
 
492
{
 
493
        return hpuxacl_sys_acl_get_fd(handle, fsp);
 
494
}
 
495
 
 
496
int sys_acl_set_file(vfs_handle_struct *handle,
 
497
                     const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
 
498
{
 
499
        return hpuxacl_sys_acl_set_file(handle, name, type, acl_d);
 
500
}
 
501
 
 
502
int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
 
503
                   SMB_ACL_T acl_d)
 
504
{
 
505
        return hpuxacl_sys_acl_set_fd(handle, fsp, acl_d);
 
506
}
 
507
 
 
508
int sys_acl_delete_def_file(vfs_handle_struct *handle,
 
509
                            const char *path)
 
510
{
 
511
        return hpuxacl_sys_acl_delete_def_file(handle, path);
 
512
}
 
513
 
 
514
#elif defined(HAVE_IRIX_ACLS)
 
515
 
 
516
SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
 
517
                           const char *path_p, SMB_ACL_TYPE_T type)
 
518
{
 
519
        return irixacl_sys_acl_get_file(handle, path_p, type);
 
520
}
 
521
 
 
522
SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
 
523
{
 
524
        return irixacl_sys_acl_get_fd(handle, fsp);
 
525
}
 
526
 
 
527
int sys_acl_set_file(vfs_handle_struct *handle,
 
528
                     const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
 
529
{
 
530
        return irixacl_sys_acl_set_file(handle, name, type, acl_d);
 
531
}
 
532
 
 
533
int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
 
534
                   SMB_ACL_T acl_d)
 
535
{
 
536
        return irixacl_sys_acl_set_fd(handle, fsp, acl_d);
 
537
}
 
538
 
 
539
int sys_acl_delete_def_file(vfs_handle_struct *handle,
 
540
                            const char *path)
 
541
{
 
542
        return irixacl_sys_acl_delete_def_file(handle, path);
 
543
}
 
544
 
 
545
#else /* No ACLs. */
 
546
 
 
547
SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
 
548
                           const char *path_p, SMB_ACL_TYPE_T type)
 
549
{
 
550
#ifdef ENOTSUP
 
551
        errno = ENOTSUP;
 
552
#else
 
553
        errno = ENOSYS;
 
554
#endif
 
555
        return NULL;
 
556
}
 
557
 
 
558
SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
 
559
{
 
560
#ifdef ENOTSUP
 
561
        errno = ENOTSUP;
 
562
#else
 
563
        errno = ENOSYS;
 
564
#endif
 
565
        return NULL;
 
566
}
 
567
 
 
568
int sys_acl_set_file(vfs_handle_struct *handle,
 
569
                     const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
 
570
{
 
571
#ifdef ENOTSUP
 
572
        errno = ENOTSUP;
 
573
#else
 
574
        errno = ENOSYS;
 
575
#endif
 
576
        return -1;
 
577
}
 
578
 
 
579
int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
 
580
                   SMB_ACL_T acl_d)
 
581
{
 
582
#ifdef ENOTSUP
 
583
        errno = ENOTSUP;
 
584
#else
 
585
        errno = ENOSYS;
 
586
#endif
 
587
        return -1;
 
588
}
 
589
 
 
590
int sys_acl_delete_def_file(vfs_handle_struct *handle,
 
591
                            const char *path)
 
592
{
 
593
#ifdef ENOTSUP
 
594
        errno = ENOTSUP;
 
595
#else
 
596
        errno = ENOSYS;
 
597
#endif
 
598
        return -1;
 
599
}
 
600
 
 
601
#endif
 
602
 
 
603
/************************************************************************
 
604
 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
 
605
 errno, 0 if not.
 
606
************************************************************************/
 
607
 
 
608
int no_acl_syscall_error(int err)
 
609
{
 
610
#if defined(ENOSYS)
 
611
        if (err == ENOSYS) {
 
612
                return 1;
 
613
        }
 
614
#endif
 
615
#if defined(ENOTSUP)
 
616
        if (err == ENOTSUP) {
 
617
                return 1;
 
618
        }
 
619
#endif
 
620
        return 0;
 
621
}