static int lock_file_1 (char *lfname, int force) { int err; int symlink_errno; USE_SAFE_ALLOCA; /* Call this first because it can GC. */ printmax_t boot = get_boot_time (); Lisp_Object luser_name = Fuser_login_name (Qnil); char const *user_name = STRINGP (luser_name) ? SSDATA (luser_name) : ""; Lisp_Object lhost_name = Fsystem_name (); char const *host_name = STRINGP (lhost_name) ? SSDATA (lhost_name) : ""; ptrdiff_t lock_info_size = (strlen (user_name) + strlen (host_name) + 2 * INT_STRLEN_BOUND (printmax_t) + sizeof "@.:"); char *lock_info_str = SAFE_ALLOCA (lock_info_size); printmax_t pid = getpid (); esprintf (lock_info_str, boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd, user_name, host_name, pid, boot); err = symlink (lock_info_str, lfname); if (errno == EEXIST && force) { unlink (lfname); err = symlink (lock_info_str, lfname); } symlink_errno = errno; SAFE_FREE (); errno = symlink_errno; return err == 0; }
static int lock_file_1 (char *lfname, int force) { register int err; time_t boot; const char *user_name; const char *host_name; char *lock_info_str; /* Call this first because it can GC. */ boot = get_boot_time (); if (STRINGP (Fuser_login_name (Qnil))) user_name = SSDATA (Fuser_login_name (Qnil)); else user_name = ""; if (STRINGP (Fsystem_name ())) host_name = SSDATA (Fsystem_name ()); else host_name = ""; lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name) + LOCK_PID_MAX + 30); if (boot) sprintf (lock_info_str, "%s@%s.%lu:%lu", user_name, host_name, (unsigned long) getpid (), (unsigned long) boot); else sprintf (lock_info_str, "%s@%s.%lu", user_name, host_name, (unsigned long) getpid ()); err = symlink (lock_info_str, lfname); if (errno == EEXIST && force) { unlink (lfname); err = symlink (lock_info_str, lfname); } return err == 0; }
static int current_lock_owner (lock_info_type *owner, char *lfname) { int ret; ptrdiff_t len; lock_info_type local_owner; intmax_t n; char *at, *dot, *colon; char readlink_buf[READLINK_BUFSIZE]; char *lfinfo = emacs_readlink (lfname, readlink_buf); /* If nonexistent lock file, all is well; otherwise, got strange error. */ if (!lfinfo) return errno == ENOENT ? 0 : -1; /* Even if the caller doesn't want the owner info, we still have to read it to determine return value. */ if (!owner) owner = &local_owner; /* Parse [email protected]:BOOT_TIME. If can't parse, return -1. */ /* The USER is everything before the last @. */ at = strrchr (lfinfo, '@'); dot = strrchr (lfinfo, '.'); if (!at || !dot) { if (lfinfo != readlink_buf) xfree (lfinfo); return -1; } len = at - lfinfo; owner->user = xmalloc (len + 1); memcpy (owner->user, lfinfo, len); owner->user[len] = 0; /* The PID is everything from the last `.' to the `:'. */ errno = 0; n = strtoimax (dot + 1, NULL, 10); owner->pid = ((0 <= n && n <= TYPE_MAXIMUM (pid_t) && (TYPE_MAXIMUM (pid_t) < INTMAX_MAX || errno != ERANGE)) ? n : 0); colon = strchr (dot + 1, ':'); /* After the `:', if there is one, comes the boot time. */ n = 0; if (colon) { errno = 0; n = strtoimax (colon + 1, NULL, 10); } owner->boot_time = ((0 <= n && n <= TYPE_MAXIMUM (time_t) && (TYPE_MAXIMUM (time_t) < INTMAX_MAX || errno != ERANGE)) ? n : 0); /* The host is everything in between. */ len = dot - at - 1; owner->host = xmalloc (len + 1); memcpy (owner->host, at + 1, len); owner->host[len] = 0; /* We're done looking at the link info. */ if (lfinfo != readlink_buf) xfree (lfinfo); /* On current host? */ if (STRINGP (Fsystem_name ()) && strcmp (owner->host, SSDATA (Fsystem_name ())) == 0) { if (owner->pid == getpid ()) ret = 2; /* We own it. */ else if (owner->pid > 0 && (kill (owner->pid, 0) >= 0 || errno == EPERM) && (owner->boot_time == 0 || within_one_second (owner->boot_time, get_boot_time ()))) ret = 1; /* An existing process on this machine owns it. */ /* The owner process is dead or has a strange pid (<=0), so try to zap the lockfile. */ else if (unlink (lfname) < 0) ret = -1; else ret = 0; } else { /* If we wanted to support the check for stale locks on remote machines, here's where we'd do it. */ ret = 1; } /* Avoid garbage. */ if (owner == &local_owner || ret <= 0) { FREE_LOCK_INFO (*owner); } return ret; }
static int current_lock_owner (lock_info_type *owner, char *lfname) { int len, ret; int local_owner = 0; char *at, *dot, *colon; char *lfinfo = 0; int bufsize = 50; /* Read arbitrarily-long contents of symlink. Similar code in file-symlink-p in fileio.c. */ do { bufsize *= 2; lfinfo = (char *) xrealloc (lfinfo, bufsize); errno = 0; len = readlink (lfname, lfinfo, bufsize); #ifdef ERANGE /* HP-UX reports ERANGE if the buffer is too small. */ if (len == -1 && errno == ERANGE) len = bufsize; #endif } while (len >= bufsize); /* If nonexistent lock file, all is well; otherwise, got strange error. */ if (len == -1) { xfree (lfinfo); return errno == ENOENT ? 0 : -1; } /* Link info exists, so `len' is its length. Null terminate. */ lfinfo[len] = 0; /* Even if the caller doesn't want the owner info, we still have to read it to determine return value, so allocate it. */ if (!owner) { owner = (lock_info_type *) alloca (sizeof (lock_info_type)); local_owner = 1; } /* Parse [email protected]:BOOT_TIME. If can't parse, return -1. */ /* The USER is everything before the last @. */ at = strrchr (lfinfo, '@'); dot = strrchr (lfinfo, '.'); if (!at || !dot) { xfree (lfinfo); return -1; } len = at - lfinfo; owner->user = (char *) xmalloc (len + 1); strncpy (owner->user, lfinfo, len); owner->user[len] = 0; /* The PID is everything from the last `.' to the `:'. */ owner->pid = atoi (dot + 1); colon = dot; while (*colon && *colon != ':') colon++; /* After the `:', if there is one, comes the boot time. */ if (*colon == ':') owner->boot_time = atoi (colon + 1); else owner->boot_time = 0; /* The host is everything in between. */ len = dot - at - 1; owner->host = (char *) xmalloc (len + 1); strncpy (owner->host, at + 1, len); owner->host[len] = 0; /* We're done looking at the link info. */ xfree (lfinfo); /* On current host? */ if (STRINGP (Fsystem_name ()) && strcmp (owner->host, SSDATA (Fsystem_name ())) == 0) { if (owner->pid == getpid ()) ret = 2; /* We own it. */ else if (owner->pid > 0 && (kill (owner->pid, 0) >= 0 || errno == EPERM) && (owner->boot_time == 0 || within_one_second (owner->boot_time, get_boot_time ()))) ret = 1; /* An existing process on this machine owns it. */ /* The owner process is dead or has a strange pid (<=0), so try to zap the lockfile. */ else if (unlink (lfname) < 0) ret = -1; else ret = 0; } else { /* If we wanted to support the check for stale locks on remote machines, here's where we'd do it. */ ret = 1; } /* Avoid garbage. */ if (local_owner || ret <= 0) { FREE_LOCK_INFO (*owner); } return ret; }