/* * mklock - create a secured lock entry with given data * (c) 2003 - willy tarreau - willy@ant-computing.com * * You may use, copy and redistribute with no restriction. Use at your own * risk, I will not be held responsible for any loss or damage. * * usage : * # mklock [data] * * This will create a symlink under , either pointing to if * is specified, or pointing to /proc/ if no data is given. * This way, the link will automatically be broken as soon as the father dies. * The name of the link will be generated randomly until no conflict happens * with an existing entry. The full pathname of the resulting link is returned * to stdout so that a script can easily use it. * This method ensures the use of a secure lock. * * Example : * # file=`mklock /tmp $$` */ #include #include #include #include #define writetxt(fd, text) write(fd, text, strlen(text)) #define LOCK_PREFIX ".lock." #define PROC_PREFIX "/proc/" #define MAX_PID_DIGITS 10 /* 10 digits do code a 32bit pid in decimal */ const char lock_prefix[] = LOCK_PREFIX; const char proc_prefix[] = PROC_PREFIX; /* writes in at most 9 decimal digits to */ void ultoa(char *to, unsigned long l) { unsigned long div = 1000000000; int zero = 1; while (div > 0) { *to = (l / div % 10) + '0'; div /= 10; zero &= (*to == '0'); if (!zero) to++; } *to = 0; } /* writes as 8 hex digits to */ void ultoh(char *to, unsigned long l) { int shift = 32; while ((shift -= 4) >= 0) { int digit = (l >> shift) & 0xf; if (digit > 9) digit += 'A' - '9' - 1; *to++ = digit + '0'; } *to = 0; } void usage() { writetxt(2, "Usage: mklock [ -d ] [ -p prefix ] [data]\n"); exit(1); } main(int argc, char **argv) { char *text, *prefix; char *directory; char *fullname; int len, num = 0, ret; int use_dir = 0; int plen; prefix = lock_prefix; argv++; argc--; while (argc > 0 && **argv == '-') { if (!strcmp(*argv, "-d")) { use_dir = 1; } else if (!strcmp(*argv, "-p")) { if (argc > 1) { argv++; argc--; prefix = argv[0]; } else usage(); } argv++; argc--; } if (argc < 1) usage(); plen = strlen(prefix); directory = argv[0]; len = strlen(directory); while (len > 0 && directory[len - 1] == '/') directory[--len] = 0; fullname = (char *)calloc(1, len + 1 + plen + 10); memcpy(fullname, directory, len); fullname[len++] = '/'; memcpy(fullname + len, prefix, plen + 1); len += plen; argv++; argc--; if (argc > 0) /* use this arg as where the link points to */ text = argv[0]; else { /* point to /proc/ */ text = (char *)malloc(strlen(PROC_PREFIX) + MAX_PID_DIGITS + 1); memcpy(text, proc_prefix, strlen(PROC_PREFIX) + 1); ultoa(text + strlen(PROC_PREFIX), getppid()); } do { /* try to create the entry with an increasing suffix until we succeed */ ultoh(fullname+len, num++); if (use_dir) ret = mkdir(fullname, 0700); else ret = symlink(text, fullname); if (ret == 0) { fullname[len + 8]='\n'; /* success, return the link or directory name */ write(1, fullname, len + 9); return 0; } } while (errno == EEXIST); /* other error, let's return 2 */ return 2; }