Skip to content

Commit

Permalink
OS-3894 want librename
Browse files Browse the repository at this point in the history
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
  • Loading branch information
rmustacc committed Feb 23, 2015
1 parent b628476 commit a18fa31
Show file tree
Hide file tree
Showing 12 changed files with 488 additions and 0 deletions.
2 changes: 2 additions & 0 deletions manifest
Expand Up @@ -4892,6 +4892,7 @@ f usr/lib/amd64/libraidcfg.so.1 0755 root bin
s usr/lib/amd64/libraidcfg.so=libraidcfg.so.1
s usr/lib/amd64/librcm.so.1=../../../lib/amd64/librcm.so.1
s usr/lib/amd64/librcm.so=../../../lib/amd64/librcm.so.1
f usr/lib/amd64/librename.so.1 0755 root bin
f usr/lib/amd64/libreparse.so.1 0755 root bin
s usr/lib/amd64/libreparse.so=libreparse.so.1
s usr/lib/amd64/libresolv.so.2=../../../lib/amd64/libresolv.so.2
Expand Down Expand Up @@ -6340,6 +6341,7 @@ s usr/lib/librcm.so.1=../../lib/librcm.so.1
s usr/lib/librcm.so=../../lib/librcm.so.1
f usr/lib/librdc.so.1 0755 root bin
s usr/lib/librdc.so=librdc.so.1
f usr/lib/librename.so.1 0755 root bin
f usr/lib/libreparse.so.1 0755 root bin
s usr/lib/libreparse.so=libreparse.so.1
s usr/lib/libresolv.so.1=../../lib/libresolv.so.1
Expand Down
2 changes: 2 additions & 0 deletions usr/src/lib/Makefile
Expand Up @@ -137,6 +137,7 @@ SUBDIRS += \
libpp \
libproc \
libproject \
librename \
libsendfile \
nametoaddr \
ncad_addr \
Expand Down Expand Up @@ -435,6 +436,7 @@ HDRSUBDIRS= \
libraidcfg \
librcm \
librdc \
librename \
libscf \
libsip \
libsmbios \
Expand Down
44 changes: 44 additions & 0 deletions usr/src/lib/librename/Makefile
@@ -0,0 +1,44 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright (c) 2014 Joyent, Inc. All rights reserved.
#

include ../Makefile.lib

HDRS = librename.h
HDRDIR = common
SUBDIRS = $(MACH)
$(BUILD64)SUBDIRS += $(MACH64)

all := TARGET = all
clean := TARGET = clean
clobber := TARGET = clobber
install := TARGET = install
lint := TARGET = lint

.KEEP_STATE:

all clean clobber lint: $(SUBDIRS)

install: $(SUBDIRS) $(VARPD_MAPFILES) install_h

install_h: $(ROOTHDRS)

check: $(CHECKHDRS)

$(SUBDIRS): FRC
@cd $@; pwd; $(MAKE) $(TARGET)

FRC:

include ../Makefile.targ
34 changes: 34 additions & 0 deletions usr/src/lib/librename/Makefile.com
@@ -0,0 +1,34 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright (c) 2014 Joyent, Inc. All rights reserved.
#

LIBRARY = librename.a
VERS = .1
OBJECTS = librename.o \

include ../../Makefile.lib

LIBS = $(DYNLIB) $(LINTLIB)
LDLIBS += -lc
CPPFLAGS += -I../common

SRCDIR = ../common

.KEEP_STATE:

all: $(LIBS)

lint: lintcheck

include ../../Makefile.targ
19 changes: 19 additions & 0 deletions usr/src/lib/librename/amd64/Makefile
@@ -0,0 +1,19 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright (c) 2014 Joyent, Inc. All rights reserved.
#

include ../Makefile.com
include ../../Makefile.lib.64

install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
229 changes: 229 additions & 0 deletions usr/src/lib/librename/common/librename.c
@@ -0,0 +1,229 @@
/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
* http://www.illumos.org/license/CDDL.
*/

/*
* Copyright (c) 2014 Joyent, Inc. All rights reserved.
*/

/*
* Implementation of librename(3RENAME) interfaces.
*/

#include <librename.h>

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <synch.h>

typedef enum librename_atomic_state {
LIBRENAME_ATOMIC_INITIAL = 0x0,
LIBRENAME_ATOMIC_FSYNC,
LIBRENAME_ATOMIC_RENAME,
LIBRENAME_ATOMIC_POSTSYNC,
LIBRENAME_ATOMIC_COMPLETED
} librename_atomic_state_t;

struct librename_atomic {
char *lra_fname; /* RO */
char *lra_altname; /* RO */
int lra_dirfd; /* RO */
int lra_tmpfd; /* RO */
mutex_t lra_lock;
librename_atomic_state_t lra_state; /* lra_lock */
};

int
librename_atomic_fdinit(int fd, const char *file, const char *prefix,
int mode, int flags, librename_atomic_t **outp)
{
int ret;
int oflags;
librename_atomic_t *lrap;
struct stat st;

if (fd < 0 || file == NULL || outp == NULL)
return (EINVAL);

if (flags & ~(LIBRENAME_ATOMIC_NOUNLINK | LIBRENAME_ATOMIC_CLOEXEC))
return (EINVAL);

if (strchr(file, '/') != NULL)
return (EINVAL);

if (prefix != NULL && strchr(prefix, '/') != NULL)
return (EINVAL);

*outp = NULL;
lrap = malloc(sizeof (librename_atomic_t));
if (lrap == NULL)
return (errno);

if (fstat(fd, &st) != 0) {
ret = errno;
free(lrap);
return (ret);
}

if (!S_ISDIR(st.st_mode)) {
free(lrap);
return (ENOTDIR);
}

if ((lrap->lra_dirfd = dup(fd)) == -1) {
ret = errno;
free(lrap);
return (ret);
}


lrap->lra_fname = strdup(file);
if (lrap->lra_fname == NULL) {
ret = errno;
if (close(lrap->lra_dirfd) != 0)
abort();
free(lrap);
return (ret);
}

if (prefix == NULL) {
ret = asprintf(&lrap->lra_altname, ".%d.%s", (int)getpid(),
file);
} else {
ret = asprintf(&lrap->lra_altname, "%s%s", prefix, file);
}
if (ret == -1) {
ret = errno;
free(lrap->lra_fname);
if (close(lrap->lra_dirfd) != 0)
abort();
free(lrap);
return (errno);
}

oflags = O_CREAT | O_TRUNC | O_RDWR | O_NOFOLLOW;
if (flags & LIBRENAME_ATOMIC_NOUNLINK)
oflags |= O_EXCL;

if (flags & LIBRENAME_ATOMIC_CLOEXEC)
oflags |= O_CLOEXEC;

lrap->lra_tmpfd = openat(lrap->lra_dirfd, lrap->lra_altname,
oflags, mode);
if (lrap->lra_tmpfd < 0) {
ret = errno;
free(lrap->lra_altname);
free(lrap->lra_fname);
if (close(lrap->lra_dirfd) != 0)
abort();
free(lrap);
return (ret);
}

if (mutex_init(&lrap->lra_lock, USYNC_THREAD, NULL) != 0)
abort();

lrap->lra_state = LIBRENAME_ATOMIC_INITIAL;
*outp = lrap;
return (0);
}

int
librename_atomic_init(const char *dir, const char *file, const char *prefix,
int mode, int flags, librename_atomic_t **outp)
{
int fd, ret;

if ((fd = open(dir, O_RDONLY)) < 0)
return (errno);

ret = librename_atomic_fdinit(fd, file, prefix, mode, flags, outp);
if (close(fd) != 0)
abort();

return (ret);
}

int
librename_atomic_fd(librename_atomic_t *lrap)
{
return (lrap->lra_tmpfd);
}

/*
* To atomically commit a file, we need to go through and do the following:
*
* o fsync the source
* o run rename
* o fsync the source again and the directory.
*/
int
librename_atomic_commit(librename_atomic_t *lrap)
{
int ret = 0;

if (mutex_lock(&lrap->lra_lock) != 0)
abort();
if (lrap->lra_state == LIBRENAME_ATOMIC_COMPLETED) {
ret = EINVAL;
goto out;
}

if (fsync(lrap->lra_tmpfd) != 0) {
ret = errno;
goto out;
}
lrap->lra_state = LIBRENAME_ATOMIC_FSYNC;

if (renameat(lrap->lra_dirfd, lrap->lra_altname, lrap->lra_dirfd,
lrap->lra_fname) != 0) {
ret = errno;
goto out;
}
lrap->lra_state = LIBRENAME_ATOMIC_RENAME;

if (fsync(lrap->lra_tmpfd) != 0) {
ret = errno;
goto out;
}
lrap->lra_state = LIBRENAME_ATOMIC_POSTSYNC;

if (fsync(lrap->lra_dirfd) != 0) {
ret = errno;
goto out;
}
lrap->lra_state = LIBRENAME_ATOMIC_COMPLETED;

out:
if (mutex_unlock(&lrap->lra_lock) != 0)
abort();
return (ret);
}

void
librename_atomic_fini(librename_atomic_t *lrap)
{

free(lrap->lra_altname);
free(lrap->lra_fname);
if (close(lrap->lra_tmpfd) != 0)
abort();
if (close(lrap->lra_dirfd) != 0)
abort();
if (mutex_destroy(&lrap->lra_lock) != 0)
abort();
free(lrap);
}

0 comments on commit a18fa31

Please sign in to comment.