bool LFLock_Maybe_Delete_File_IMP(LockFileLock *self, String *path, bool delete_mine, bool delete_other) { LockFileLockIVARS *const ivars = LFLock_IVARS(self); Folder *folder = ivars->folder; bool success = false; // Only delete locks that start with our lock name. if (!Str_Starts_With_Utf8(path, "locks", 5)) { return false; } StringIterator *iter = Str_Top(path); StrIter_Advance(iter, 5 + 1); if (!StrIter_Starts_With(iter, ivars->name)) { DECREF(iter); return false; } DECREF(iter); // Attempt to delete dead lock file. if (Folder_Exists(folder, path)) { Hash *hash = (Hash*)Json_slurp_json(folder, path); if (hash != NULL && Obj_Is_A((Obj*)hash, HASH)) { String *pid_buf = (String*)Hash_Fetch_Utf8(hash, "pid", 3); String *host = (String*)Hash_Fetch_Utf8(hash, "host", 4); String *name = (String*)Hash_Fetch_Utf8(hash, "name", 4); // Match hostname and lock name. if (host != NULL && Str_Is_A(host, STRING) && Str_Equals(host, (Obj*)ivars->host) && name != NULL && Str_Is_A(name, STRING) && Str_Equals(name, (Obj*)ivars->name) && pid_buf != NULL && Str_Is_A(pid_buf, STRING) ) { // Verify that pid is either mine or dead. int pid = (int)Str_To_I64(pid_buf); if ((delete_mine && pid == PID_getpid()) // This process. || (delete_other && !PID_active(pid)) // Dead pid. ) { if (Folder_Delete(folder, path)) { success = true; } else { String *mess = MAKE_MESS("Can't delete '%o'", path); DECREF(hash); Err_throw_mess(ERR, mess); } } } } DECREF(hash); } return success; }
static void test_iterator_substring(TestBatchRunner *runner) { String *string = Str_newf("a%sb%sc%sd", smiley, smiley, smiley); StringIterator *start = Str_Top(string); StringIterator *end = Str_Tail(string); { String *substring = StrIter_crop(start, end); TEST_TRUE(runner, Str_Equals(substring, (Obj*)string), "StrIter_crop whole string"); DECREF(substring); } StrIter_Advance(start, 2); StrIter_Recede(end, 2); { String *substring = StrIter_crop(start, end); String *wanted = Str_newf("b%sc", smiley); TEST_TRUE(runner, Str_Equals(substring, (Obj*)wanted), "StrIter_crop"); TEST_TRUE(runner, StrIter_Starts_With(start, wanted), "Starts_With returns true"); TEST_TRUE(runner, StrIter_Ends_With(end, wanted), "Ends_With returns true"); DECREF(wanted); DECREF(substring); } { String *short_str = Str_newf("b%sx", smiley); TEST_FALSE(runner, StrIter_Starts_With(start, short_str), "Starts_With returns false"); TEST_FALSE(runner, StrIter_Ends_With(start, short_str), "Ends_With returns false"); String *long_str = Str_newf("b%sxxxxxxxxxxxx%sc", smiley, smiley); TEST_FALSE(runner, StrIter_Starts_With(start, long_str), "Starts_With long string returns false"); TEST_FALSE(runner, StrIter_Ends_With(end, long_str), "Ends_With long string returns false"); DECREF(short_str); DECREF(long_str); } { String *substring = StrIter_crop(end, NULL); String *wanted = Str_newf("%sd", smiley); TEST_TRUE(runner, Str_Equals(substring, (Obj*)wanted), "StrIter_crop with NULL tail"); DECREF(wanted); DECREF(substring); } { String *substring = StrIter_crop(NULL, start); String *wanted = Str_newf("a%s", smiley); TEST_TRUE(runner, Str_Equals(substring, (Obj*)wanted), "StrIter_crop with NULL top"); DECREF(wanted); DECREF(substring); } DECREF(start); DECREF(end); DECREF(string); }