glusterfs

Форк
0
618 строк · 15.0 Кб
1
/*
2
  Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
3
  This file is part of GlusterFS.
4

5
  This file is licensed to you under your choice of the GNU Lesser
6
  General Public License, version 3 or any later version (LGPLv3 or
7
  later), or the GNU General Public License, version 2 (GPLv2), in all
8
  cases as published by the Free Software Foundation.
9
*/
10

11
#include <stdlib.h>
12
#include <unistd.h>
13
#include <stdarg.h>
14
#include <getopt.h>
15
#include <sys/types.h>
16
#include <dirent.h>
17

18
#include "glusterfs/logging.h"
19
#include "glusterfs/compat.h"
20
#include "glusterfs/iatt.h"
21
#include "glusterfs/syscall.h"
22
#include "glusterfs/run.h"
23
#include "glusterfs/libglusterfs-messages.h"
24

25
#ifdef GF_SOLARIS_HOST_OS
26
int
27
solaris_fsetxattr(int fd, const char *key, const char *value, size_t size,
28
                  int flags)
29
{
30
    int attrfd = -1;
31
    int ret = 0;
32

33
    attrfd = openat(fd, key, flags | O_CREAT | O_WRONLY | O_XATTR, 0777);
34
    if (attrfd >= 0) {
35
        ftruncate(attrfd, 0);
36
        ret = write(attrfd, value, size);
37
        close(attrfd);
38
    } else {
39
        if (errno != ENOENT)
40
            gf_msg("libglusterfs", GF_LOG_ERROR, errno,
41
                   LG_MSG_SET_ATTRIBUTE_FAILED,
42
                   "Couldn't set "
43
                   "extended attribute for %d",
44
                   fd);
45
        return -1;
46
    }
47

48
    return 0;
49
}
50

51
int
52
solaris_fgetxattr(int fd, const char *key, char *value, size_t size)
53
{
54
    int attrfd = -1;
55
    int ret = 0;
56

57
    attrfd = openat(fd, key, O_RDONLY | O_XATTR);
58
    if (attrfd >= 0) {
59
        if (size == 0) {
60
            struct stat buf;
61
            fstat(attrfd, &buf);
62
            ret = buf.st_size;
63
        } else {
64
            ret = read(attrfd, value, size);
65
        }
66
        close(attrfd);
67
    } else {
68
        if (errno != ENOENT)
69
            gf_msg("libglusterfs", GF_LOG_INFO, errno,
70
                   LG_MSG_READ_ATTRIBUTE_FAILED,
71
                   "Couldn't read "
72
                   "extended attribute for the file %d",
73
                   fd);
74
        if (errno == ENOENT)
75
            errno = ENODATA;
76
        return -1;
77
    }
78

79
    return ret;
80
}
81

82
/* Solaris does not support xattr for symlinks and dev files. Since gfid and
83
   other trusted attributes are stored as xattrs, we need to provide support for
84
   them. A mapped regular file is stored in the /.glusterfs_xattr_inode of the
85
   export dir. All xattr ops related to the special files are redirected to this
86
   map file.
87
*/
88

89
int
90
make_export_path(const char *real_path, char **path)
91
{
92
    int ret = -1;
93
    char *tmp = NULL;
94
    char *export_path = NULL;
95
    char *dup = NULL;
96
    char *ptr = NULL;
97
    char *freeptr = NULL;
98
    uuid_t gfid = {
99
        0,
100
    };
101

102
    export_path = GF_CALLOC(1, sizeof(char) * PATH_MAX, 0);
103
    if (!export_path)
104
        goto out;
105

106
    dup = gf_strdup(real_path);
107
    if (!dup)
108
        goto out;
109

110
    freeptr = dup;
111
    ret = solaris_getxattr("/", GFID_XATTR_KEY, gfid, 16);
112
    /* Return value of getxattr */
113
    if (ret == 16) {
114
        if (__is_root_gfid(gfid)) {
115
            strcat(export_path, "/");
116
            ret = 0;
117
            goto done;
118
        }
119
    }
120

121
    do {
122
        ptr = strtok_r(dup, "/", &tmp);
123
        if (!ptr)
124
            break;
125
        strcat(export_path, dup);
126
        ret = solaris_getxattr(export_path, GFID_XATTR_KEY, gfid, 16);
127
        if (ret == 16) {
128
            if (__is_root_gfid(gfid)) {
129
                ret = 0;
130
                goto done;
131
            }
132
        }
133
        strcat(export_path, "/");
134
        dup = tmp;
135
    } while (ptr);
136

137
    goto out;
138

139
done:
140
    if (!ret) {
141
        *path = export_path;
142
    }
143
out:
144
    GF_FREE(freeptr);
145
    if (ret && export_path)
146
        GF_FREE(export_path);
147

148
    return ret;
149
}
150
int
151
solaris_xattr_resolve_path(const char *real_path, char **path)
152
{
153
    int ret = -1;
154
    char *export_path = NULL;
155
    char xattr_path[PATH_MAX] = {
156
        0,
157
    };
158
    struct stat lstatbuf = {
159
        0,
160
    };
161
    struct iatt stbuf = {
162
        0,
163
    };
164
    struct stat statbuf = {
165
        0,
166
    };
167

168
    ret = lstat(real_path, &lstatbuf);
169
    if (ret != 0)
170
        return ret;
171
    iatt_from_stat(&stbuf, &lstatbuf);
172
    if (IA_ISREG(stbuf.ia_type) || IA_ISDIR(stbuf.ia_type))
173
        return -1;
174

175
    ret = make_export_path(real_path, &export_path);
176
    if (!ret && export_path) {
177
        strcat(export_path, "/" GF_SOLARIS_XATTR_DIR);
178
        if (lstat(export_path, &statbuf)) {
179
            ret = mkdir(export_path, 0755);
180
            if (ret && (errno != EEXIST)) {
181
                gf_msg_debug(THIS->name, 0,
182
                             "mkdir failed,"
183
                             " errno: %d",
184
                             errno);
185
                goto out;
186
            }
187
        }
188

189
        snprintf(xattr_path, PATH_MAX, "%s%s%lu", export_path, "/",
190
                 stbuf.ia_ino);
191

192
        ret = lstat(xattr_path, &statbuf);
193

194
        if (ret) {
195
            ret = mknod(xattr_path, S_IFREG | O_WRONLY, 0);
196
            if (ret && (errno != EEXIST)) {
197
                gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_FILE_OP_FAILED,
198
                       "Failed to "
199
                       "create mapped file %s",
200
                       xattr_path);
201
                goto out;
202
            }
203
        }
204
        *path = gf_strdup(xattr_path);
205
    }
206
out:
207
    GF_FREE(export_path);
208
    if (*path)
209
        return 0;
210
    else
211
        return -1;
212
}
213

214
int
215
solaris_setxattr(const char *path, const char *key, const char *value,
216
                 size_t size, int flags)
217
{
218
    int attrfd = -1;
219
    int ret = 0;
220
    char *mapped_path = NULL;
221

222
    ret = solaris_xattr_resolve_path(path, &mapped_path);
223
    if (!ret) {
224
        attrfd = attropen(mapped_path, key, flags | O_CREAT | O_WRONLY, 0777);
225
    } else {
226
        attrfd = attropen(path, key, flags | O_CREAT | O_WRONLY, 0777);
227
    }
228
    if (attrfd >= 0) {
229
        ftruncate(attrfd, 0);
230
        ret = write(attrfd, value, size);
231
        close(attrfd);
232
        ret = 0;
233
    } else {
234
        if (errno != ENOENT)
235
            gf_msg("libglusterfs", GF_LOG_ERROR, errno,
236
                   LG_MSG_SET_ATTRIBUTE_FAILED,
237
                   "Couldn't set "
238
                   "extended attribute for %s",
239
                   path);
240
        ret = -1;
241
    }
242
    GF_FREE(mapped_path);
243
    return ret;
244
}
245

246
int
247
solaris_listxattr(const char *path, char *list, size_t size)
248
{
249
    int attrdirfd = -1;
250
    ssize_t len = 0;
251
    DIR *dirptr = NULL;
252
    struct dirent *dent = NULL;
253
    int newfd = -1;
254
    char *mapped_path = NULL;
255
    int ret = -1;
256

257
    ret = solaris_xattr_resolve_path(path, &mapped_path);
258
    if (!ret) {
259
        attrdirfd = attropen(mapped_path, ".", O_RDONLY, 0);
260
    } else {
261
        attrdirfd = attropen(path, ".", O_RDONLY, 0);
262
    }
263
    if (attrdirfd >= 0) {
264
        newfd = dup(attrdirfd);
265
        dirptr = fdopendir(newfd);
266
        if (dirptr) {
267
            while ((dent = readdir(dirptr))) {
268
                size_t listlen = strlen(dent->d_name);
269
                if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) {
270
                    /* we don't want "." and ".." here */
271
                    continue;
272
                }
273
                if (size == 0) {
274
                    /* return the current size of the list
275
                       of extended attribute names*/
276
                    len += listlen + 1;
277
                } else {
278
                    /* check size and copy entry + null
279
                       into list. */
280
                    if ((len + listlen + 1) > size) {
281
                        errno = ERANGE;
282
                        len = -1;
283
                        break;
284
                    } else {
285
                        strncpy(list + len, dent->d_name, listlen);
286
                        len += listlen;
287
                        list[len] = '\0';
288
                        ++len;
289
                    }
290
                }
291
            }
292

293
            if (closedir(dirptr) == -1) {
294
                close(attrdirfd);
295
                len = -1;
296
                goto out;
297
            }
298
        } else {
299
            close(attrdirfd);
300
            len = -1;
301
            goto out;
302
        }
303
        close(attrdirfd);
304
    }
305
out:
306
    GF_FREE(mapped_path);
307
    return len;
308
}
309

310
int
311
solaris_flistxattr(int fd, char *list, size_t size)
312
{
313
    int attrdirfd = -1;
314
    ssize_t len = 0;
315
    DIR *dirptr = NULL;
316
    struct dirent *dent = NULL;
317
    int newfd = -1;
318

319
    attrdirfd = openat(fd, ".", O_RDONLY, 0);
320
    if (attrdirfd >= 0) {
321
        newfd = dup(attrdirfd);
322
        dirptr = fdopendir(newfd);
323
        if (dirptr) {
324
            while ((dent = readdir(dirptr))) {
325
                size_t listlen = strlen(dent->d_name);
326
                if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) {
327
                    /* we don't want "." and ".." here */
328
                    continue;
329
                }
330
                if (size == 0) {
331
                    /* return the current size of the list
332
                       of extended attribute names*/
333
                    len += listlen + 1;
334
                } else {
335
                    /* check size and copy entry + null
336
                       into list. */
337
                    if ((len + listlen + 1) > size) {
338
                        errno = ERANGE;
339
                        len = -1;
340
                        break;
341
                    } else {
342
                        strncpy(list + len, dent->d_name, listlen);
343
                        len += listlen;
344
                        list[len] = '\0';
345
                        ++len;
346
                    }
347
                }
348
            }
349

350
            if (closedir(dirptr) == -1) {
351
                close(attrdirfd);
352
                return -1;
353
            }
354
        } else {
355
            close(attrdirfd);
356
            return -1;
357
        }
358
        close(attrdirfd);
359
    }
360
    return len;
361
}
362

363
int
364
solaris_removexattr(const char *path, const char *key)
365
{
366
    int ret = -1;
367
    int attrfd = -1;
368
    char *mapped_path = NULL;
369

370
    ret = solaris_xattr_resolve_path(path, &mapped_path);
371
    if (!ret) {
372
        attrfd = attropen(mapped_path, ".", O_RDONLY, 0);
373
    } else {
374
        attrfd = attropen(path, ".", O_RDONLY, 0);
375
    }
376
    if (attrfd >= 0) {
377
        ret = unlinkat(attrfd, key, 0);
378
        close(attrfd);
379
    } else {
380
        if (errno == ENOENT)
381
            errno = ENODATA;
382
        ret = -1;
383
    }
384

385
    GF_FREE(mapped_path);
386

387
    return ret;
388
}
389

390
int
391
solaris_getxattr(const char *path, const char *key, char *value, size_t size)
392
{
393
    int attrfd = -1;
394
    int ret = 0;
395
    char *mapped_path = NULL;
396

397
    ret = solaris_xattr_resolve_path(path, &mapped_path);
398
    if (!ret) {
399
        attrfd = attropen(mapped_path, key, O_RDONLY, 0);
400
    } else {
401
        attrfd = attropen(path, key, O_RDONLY, 0);
402
    }
403

404
    if (attrfd >= 0) {
405
        if (size == 0) {
406
            struct stat buf;
407
            fstat(attrfd, &buf);
408
            ret = buf.st_size;
409
        } else {
410
            ret = read(attrfd, value, size);
411
        }
412
        close(attrfd);
413
    } else {
414
        if (errno != ENOENT)
415
            gf_msg("libglusterfs", GF_LOG_INFO, errno,
416
                   LG_MSG_READ_ATTRIBUTE_FAILED,
417
                   "Couldn't read "
418
                   "extended attribute for the file %s",
419
                   path);
420
        if (errno == ENOENT)
421
            errno = ENODATA;
422
        ret = -1;
423
    }
424
    GF_FREE(mapped_path);
425
    return ret;
426
}
427

428
char *
429
strsep(char **str, const char *delims)
430
{
431
    char *token;
432

433
    if (*str == NULL) {
434
        /* No more tokens */
435
        return NULL;
436
    }
437

438
    token = *str;
439
    while (**str != '\0') {
440
        if (strchr(delims, **str) != NULL) {
441
            **str = '\0';
442
            (*str)++;
443
            return token;
444
        }
445
        (*str)++;
446
    }
447
    /* There is no other token */
448
    *str = NULL;
449
    return token;
450
}
451

452
/* Code comes from libiberty */
453

454
int
455
vasprintf(char **result, const char *format, va_list args)
456
{
457
    return gf_vasprintf(result, format, args);
458
}
459

460
int
461
asprintf(char **buf, const char *fmt, ...)
462
{
463
    int status;
464
    va_list ap;
465

466
    va_start(ap, fmt);
467
    status = vasprintf(buf, fmt, ap);
468
    va_end(ap);
469
    return status;
470
}
471

472
int
473
solaris_unlink(const char *path)
474
{
475
    char *mapped_path = NULL;
476
    struct stat stbuf = {
477
        0,
478
    };
479
    int ret = -1;
480

481
    ret = solaris_xattr_resolve_path(path, &mapped_path);
482

483
    if (!ret && mapped_path) {
484
        if (lstat(path, &stbuf)) {
485
            gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_FILE_OP_FAILED,
486
                   "Stat failed on "
487
                   "mapped file %s",
488
                   mapped_path);
489
            goto out;
490
        }
491
        if (stbuf.st_nlink == 1) {
492
            if (remove(mapped_path))
493
                gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_FILE_OP_FAILED,
494
                       "Failed to "
495
                       "remove mapped file %s",
496
                       mapped_path);
497
        }
498
    }
499

500
out:
501
    GF_FREE(mapped_path);
502

503
    return unlink(path);
504
}
505

506
int
507
solaris_rename(const char *old_path, const char *new_path)
508
{
509
    char *mapped_path = NULL;
510
    int ret = -1;
511

512
    ret = solaris_xattr_resolve_path(new_path, &mapped_path);
513

514
    if (!ret && mapped_path) {
515
        if (!remove(mapped_path))
516
            gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_FILE_OP_FAILED,
517
                   "Failed to remove "
518
                   "mapped file %s.",
519
                   mapped_path);
520
        GF_FREE(mapped_path);
521
    }
522

523
    return rename(old_path, new_path);
524
}
525

526
char *
527
mkdtemp(char *tempstring)
528
{
529
    char *new_string = NULL;
530
    int ret = 0;
531

532
    new_string = mkstemp(tempstring);
533
    if (!new_string)
534
        goto out;
535

536
    ret = mkdir(new_string, 0700);
537
    if (ret < 0)
538
        new_string = NULL;
539

540
out:
541
    return new_string;
542
}
543

544
#endif /* GF_SOLARIS_HOST_OS */
545

546
#ifdef GF_BSD_HOST_OS
547
void
548
gf_extattr_list_reshape(char *bsd_list, ssize_t size)
549
{
550
    /*
551
     * the format of bsd_list is
552
     *     <attr_len>attr<attr_len>attr...
553
     * we try to reformat it as Linux's
554
     *     attr<\0>attr<\0>...
555
     * */
556
    if (NULL == bsd_list || size <= 0)
557
        return;
558

559
    size_t i = 0, j;
560

561
    while (i < size) {
562
        size_t attr_len = bsd_list[i];
563

564
        for (j = i; j < i + attr_len; ++j)
565
            bsd_list[j] = bsd_list[j + 1];
566
        bsd_list[j] = '\0';
567

568
        i += attr_len + 1;
569
        gf_msg_debug("syscall", 0, "syscall debug: %lu", attr_len);
570
    }
571
}
572
#endif /* GF_BSD_HOST_OS */
573

574
#ifndef HAVE_STRNLEN
575
size_t
576
strnlen(const char *string, size_t maxlen)
577
{
578
    int len = 0;
579
    while ((len < maxlen) && string[len])
580
        len++;
581
    return len;
582
}
583
#endif /* STRNLEN */
584

585
int
586
gf_umount_lazy(char *xlname, char *path, int rmdir_flag)
587
{
588
    int ret = -1;
589
    runner_t runner = {
590
        0,
591
    };
592

593
    runinit(&runner);
594
#ifdef GF_LINUX_HOST_OS
595
    runner_add_args(&runner, _PATH_UMOUNT, "-l", path, NULL);
596
#else
597
    if (rmdir_flag)
598
        runner_add_args(&runner, SBIN_DIR "/umountd", "-r", path, NULL);
599
    else
600
        runner_add_args(&runner, SBIN_DIR "/umountd", path, NULL);
601
#endif
602
    ret = runner_run(&runner);
603
    if (ret) {
604
        gf_msg(xlname, GF_LOG_ERROR, errno, LG_MSG_UNMOUNT_FAILED,
605
               "Lazy unmount of %s", path);
606
    }
607

608
#ifdef GF_LINUX_HOST_OS
609
    if (!ret && rmdir_flag) {
610
        ret = sys_rmdir(path);
611
        if (ret)
612
            gf_msg(xlname, GF_LOG_WARNING, errno, LG_MSG_DIR_OP_FAILED,
613
                   "rmdir %s", path);
614
    }
615
#endif
616

617
    return ret;
618
}
619

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.