/* * file-lock.c * * Copyright (C) 2008 Oracle Inc. * Copyright (C) 2008 Zhigang Wang * * 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 3 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, see . */ #include #include #include #include #include #include #include #include #include const char version[] = "0.0.1"; static char short_opts[] = "lup:d:n:hvV"; static struct option long_opts[] = { { "lock", no_argument, NULL, 'l' }, { "unlock", no_argument, NULL, 'u' }, { "path", required_argument, NULL, 'p' }, { "name", required_argument, NULL, 'n' }, { "uuid", required_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, { "verbose", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 } }; static void usage(char *prog, FILE *fp, int n) { fprintf(fp, "usage: %s [options]\n", prog); fprintf(fp, "\n"); fprintf(fp, "options:\n"); fprintf(fp, " -l, --lock Acquire the lock.\n"); fprintf(fp, " -u, --unlock Release the lock.\n"); fprintf(fp, " -p, --path Set the path for the locks.\n"); fprintf(fp, " -n, --name Set the name of the VM.\n"); fprintf(fp, " -d, --uuid Set the uuid of the VM.\n"); fprintf(fp, " -v, --verbose Show more infomation.\n"); fprintf(fp, " -V, --version Show version number and exit.\n"); fprintf(fp, " -h, --help Show this help information.\n"); fprintf(fp, "\n"); exit(n); } static int do_lock(char *path, char *name, char *uuid) { char *fn; int fd; if (asprintf(&fn, "%s/%s-%s.lock", path, name, uuid) == -1) return -1; fd = open(fn, O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (fd == -1) { free(fn); return errno; } free(fn); close(fd); return 0; } static int do_unlock(char *path, char *name, char *uuid) { char *fn; if (asprintf(&fn, "%s/%s-%s.lock", path, name, uuid) == -1) return -1; if (unlink(fn) == -1) { free(fn); return errno; } free(fn); return 0; } int main(int argc, char *argv[]) { char *prog, *p; char *name = NULL; char *uuid = NULL; char *path = "."; /* create lock file on current working directory by default*/ int verbose = 0; /* turn off verbose output by default */ int status = 0; /* returned value */ int lock = 0, unlock = 0; int c; prog = argv[0]; p = strrchr(prog, '/'); if (p) prog = p+1; while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { switch (c) { case 'l': /* acquire the lock */ lock = 1; break; case 'u': /* release the lock */ unlock = 1; break; case 'p': /* path for lock file */ path = optarg; break; case 'n': /* name of vm */ name = optarg; break; case 'd': /* uuid of vm */ uuid = optarg; break; case 'h': /* help */ usage(prog, stdout, 0); break; case 'v': /* be chatty */ ++verbose; break; case 'V': /* version */ fprintf(stdout, "%s: %s\n", prog, version); exit(0); case 0: break; case '?': default: usage(prog, stderr, 1); } } if (optind < argc) usage(prog, stderr, 1); if (name==NULL || uuid==NULL) { fprintf(stderr, "you should specify the name and uuid of vm.\n\n"); usage(prog, stderr, 1); } if (lock && unlock) { fprintf(stderr, "cannot execute lock and unlock at the same time.\n\n"); usage(prog, stderr, 1); } if (lock) { if (verbose) fprintf(stdout, "creating lock file %s/%s-%s.lock\n", path, name, uuid); status = do_lock(path, name, uuid); if (verbose) if (status == 0) fprintf(stdout, "lock sucess.\n"); else fprintf(stdout, "lock failed.\n"); } else if (unlock) { if (verbose) fprintf(stdout, "removing lock file %s/%s-%s.lock\n", path, name, uuid); status = do_unlock(path, name, uuid); if (verbose) if (status == 0) fprintf(stdout, "unlock sucess.\n"); else fprintf(stdout, "unlock failed.\n"); } else { fprintf(stderr, "you should specify lock or unlock.\n\n"); usage(prog, stderr, 1); } return status; }