file-lock.c revision 0dc7891233a973829f00371b27810f849b987c66
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2002-2014 Dovecot authors, see the included COPYING file */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenbool file_lock_method_parse(const char *name, enum file_lock_method *method_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *file_lock_method_to_str(enum file_lock_method method)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return "fcntl";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return "flock";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return "dotlock";
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainenint file_try_lock(int fd, const char *path, int lock_type,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return file_wait_lock(fd, path, lock_type, lock_method, 0, lock_r);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenint file_try_lock_error(int fd, const char *path, int lock_type,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen struct file_lock **lock_r, const char **error_r)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen return file_wait_lock_error(fd, path, lock_type, lock_method, 0,
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainenstatic int file_lock_do(int fd, const char *path, int lock_type,
dfaefeabae939803ceb8c503101e86b5496541d1Timo Sirainen unsigned int timeout_secs, const char **error_r)
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen lock_type_str = lock_type == F_UNLCK ? "unlock" :
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen (lock_type == F_RDLCK ? "read-lock" : "write-lock");
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen "Can't lock file %s: fcntl() locks not supported", path);
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen ret = fcntl(fd, timeout_secs ? F_SETLKW : F_SETLK, &fl);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* locked by another process */
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "fcntl(%s, %s, F_SETLK) locking failed: %m "
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "(File is already locked)", path, lock_type_str);
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen /* most likely alarm hit, meaning we timeouted.
8d630c15a8ed6f85553467c3a231a273defca5f6Timo Sirainen even if not, we probably want to be killed
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen so stop blocking. */
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen "fcntl(%s, %s, F_SETLKW) locking failed: "
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen "Timed out after %u seconds",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = t_strdup_printf("fcntl(%s, %s, %s) locking failed: %m",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen path, lock_type_str, timeout_secs == 0 ? "F_SETLK" : "F_SETLKW");
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen "Can't lock file %s: flock() not supported", path);
cff1f182205e674285cf3ff446a0dcf7afea277dTimo Sirainen int operation = timeout_secs != 0 ? 0 : LOCK_NB;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen if (timeout_secs == 0 && errno == EWOULDBLOCK) {
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen /* locked by another process */
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen "flock(%s, %s) failed: %m "
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen "(File is already locked)", path, lock_type_str);
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen *error_r = t_strdup_printf("flock(%s, %s) failed: "
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen "Timed out after %u seconds",
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen *error_r = t_strdup_printf("flock(%s, %s) failed: %m",
4b41116563110d00330896a568eff1078c382827Timo Sirainen /* we shouldn't get here */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenint file_wait_lock(int fd, const char *path, int lock_type,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ret = file_wait_lock_error(fd, path, lock_type, lock_method,
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainenint file_wait_lock_error(int fd, const char *path, int lock_type,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen struct file_lock **lock_r, const char **error_r)
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen ret = file_lock_do(fd, path, lock_type, lock_method, timeout_secs, error_r);
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainenint file_lock_try_update(struct file_lock *lock, int lock_type)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return file_lock_do(lock->fd, lock->path, lock_type,
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen if (file_lock_do(lock->fd, lock->path, F_UNLCK,
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen /* this shouldn't happen */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_error("file_unlock(%s) failed: %m", lock->path);