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; }