/* Copyright (C) 2008 Dmitry V. Levin "lock" builtin implementation for GNU bash. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #include "builtins.h" #include "shell.h" #include "bashgetopt.h" #include "common.h" #include "filecntl.h" static int lock_file(const char *fname, int operation, int verbose) { int fd, flags = O_RDONLY | O_NOCTTY; if (operation & LOCK_NB) flags |= O_NONBLOCK; fd = open(fname, flags | O_CREAT, 0666); if (fd < 0 && errno == EISDIR) fd = open(fname, flags); if (fd < 0) { builtin_error("Failed to open file %s: %m", fname); return -1; } fd = move_to_high_fd(fd, 1, -1); SET_CLOSE_ON_EXEC(fd); if (flock(fd, operation) == 0) return 0; if (verbose) builtin_error("Failed to place a lock on file %s: %m", fname); close(fd); return -1; } static int lockf_builtin (WORD_LIST *list) { int opt, operation = LOCK_EX, nonblock = 0, verbose = 0; reset_internal_getopt(); while ((opt = internal_getopt(list, "ensvx")) != -1) { switch (opt) { case 'e': case 'x': operation = LOCK_EX; break; case 's': operation = LOCK_SH; break; case 'n': nonblock = LOCK_NB; break; case 'v': verbose = 1; break; default: builtin_usage(); return EX_USAGE; } } list = loptend; if (!list || list->next) { builtin_usage(); return EX_USAGE; } return lock_file(list->word->word, operation | nonblock, verbose) ? EXECUTION_FAILURE : EXECUTION_SUCCESS; } static char *lockf_doc[] = { "Locks a specified file, which is created if it does not already exist.", "File descriptor of the opened file has the close-on-exec flag set.", "Options have the following meanings:", " ", " -s obtain a shared lock, sometimes called a read lock", " -e, -x obtain an exclusive lock, sometimes called a write lock", " (this is the default)", " -n fail rather than wait if the lock cannot be immediately acquired", " -v complain when lock attempt fails", NULL }; struct builtin lockf_struct = { "lockf", /* builtin name */ lockf_builtin, /* function implementing the builtin */ BUILTIN_ENABLED, /* initial flags for builtin */ lockf_doc, /* array of long documentation strings. */ "lockf [-ensx] file", /* usage synopsis; becomes short_doc */ 0 /* reserved for internal use */ };