Data-Stack-Shared

 view release on metacpan or  search on metacpan

eg/str_undo.pl  view on Meta::CPAN

use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/../blib/lib", "$FindBin::Bin/../blib/arch";
use Data::Stack::Shared;
$| = 1;

my $undo = Data::Stack::Shared::Str->new(undef, 50, 128);

# simulate operations
for my $op ("create file.txt", "write 100 bytes", "chmod 644", "rename to file.bak") {
    $undo->push($op);
    printf "do: %s\n", $op;
}
printf "\nstack size: %d\n\n", $undo->size;

# undo last 2
for (1..2) {
    my $op = $undo->pop;
    printf "undo: %s\n", $op;
}

stack.h  view on Meta::CPAN

    return 1;
}

/* Securely obtain a fd: create exclusively (O_CREAT|O_EXCL|O_NOFOLLOW at mode,
 * default 0600), or attach an existing file (O_RDWR|O_NOFOLLOW, no O_CREAT).
 * O_EXCL blocks a pre-seeded/hard-linked file and O_NOFOLLOW a symlink swap,
 * so a local peer cannot redirect or pre-own the backing segment. */
static int stk_secure_open(const char *path, mode_t mode, char *errbuf) {
    for (int attempt = 0; attempt < 100; attempt++) {
        int fd = open(path, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, mode);
        if (fd >= 0) { (void)fchmod(fd, mode); return fd; }   /* exact mode: umask narrowed the O_EXCL create */
        if (errno != EEXIST) { STK_ERR("create %s: %s", path, strerror(errno)); return -1; }
        fd = open(path, O_RDWR|O_NOFOLLOW|O_CLOEXEC);
        if (fd >= 0) return fd;
        if (errno == ENOENT) continue;   /* creator unlinked between our two opens; retry */
        STK_ERR("open %s: %s", path, strerror(errno));  /* ELOOP => symlink rejected */
        return -1;
    }
    STK_ERR("open %s: create/attach kept racing", path);
    return -1;
}

stack.h  view on Meta::CPAN

        struct stat st;
        if (fstat(fd, &st) < 0) {
            STK_ERR("fstat: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL;
        }
        int is_new = (st.st_size == 0);
        if (!is_new && (uint64_t)st.st_size < sizeof(StkHeader)) {
            STK_ERR("%s: file too small (%lld)", path, (long long)st.st_size);
            flock(fd, LOCK_UN); close(fd); return NULL;
        }

        if (is_new && (st.st_uid != geteuid() || fchmod(fd, mode) < 0)) {
            STK_ERR("%s: refusing to initialize file not owned by us", path);
            flock(fd, LOCK_UN); close(fd); return NULL;
        }
        if (is_new) {
            if (ftruncate(fd, (off_t)total) < 0) {
                STK_ERR("ftruncate: %s", strerror(errno));
                flock(fd, LOCK_UN); close(fd); return NULL;
            }
        }
        map_size = is_new ? (size_t)total : (size_t)st.st_size;

stack.h  view on Meta::CPAN

            memcpy(&snap, base, sizeof snap);
            if (!stk_validate_header(&snap, (uint64_t)st.st_size, variant_id)) {
                /* Recover an abandoned mid-init file: a creator killed
                 * between the ftruncate and the header init leaves a
                 * full-size, all-zero (magic==0) file that would brick every
                 * future open of this path.  Re-initialize ONLY when it is
                 * exactly our size, still uninitialized, and owned by us;
                 * anything else still errors. */
                if (snap.magic == 0 && (uint64_t)st.st_size == total
                    && st.st_uid == geteuid() && stk_region_is_zero(base, map_size)) {
                    if (fchmod(fd, mode) < 0) {
                        STK_ERR("%s: fchmod: %s", path, strerror(errno));
                        munmap(base, map_size); flock(fd, LOCK_UN); close(fd); return NULL;
                    }
                    stk_init_header(base, total, elem_size, variant_id, capacity);
                    flock(fd, LOCK_UN); close(fd);
                    return stk_setup(base, map_size, path, -1,
                                     sizeof(StkHeader), stk_ctl_offset(elem_size, capacity),
                                     elem_size, capacity);
                }
                if (snap.magic == 0 && (uint64_t)st.st_size == total
                    && st.st_uid == geteuid())



( run in 1.273 second using v1.01-cache-2.11-cpan-f03e8824b8d )