diff -Nru dspam-3.8.0.orig/src/hash_drv.c dspam-3.8.0/src/hash_drv.c --- dspam-3.8.0.orig/src/hash_drv.c 2007-12-09 13:24:55.000000000 +0200 +++ dspam-3.8.0/src/hash_drv.c 2007-12-09 13:25:46.000000000 +0200 @@ -251,14 +251,14 @@ int _hash_drv_lock_get ( - const char *home, + DSPAM_CTX *CTX, struct _hash_drv_storage *s, const char *username) { char filename[MAX_FILENAME_LENGTH]; int r; - _ds_userdir_path(filename, home, username, "lock"); + _ds_userdir_path(filename, CTX->home, username, "lock"); _ds_prepare_path_for(filename); s->lock = fopen(filename, "a"); @@ -294,6 +294,57 @@ return r; } +FILE* +_hash_tools_lock_get (const char *cssfilename) +{ + char filename[MAX_FILENAME_LENGTH]; + char *pPeriod; + int r; + FILE* lockfile = NULL; + + if (cssfilename == NULL) + return NULL; + pPeriod = strrchr(cssfilename, '.'); + if (pPeriod == NULL || strcmp(pPeriod + 1, "css") || pPeriod - cssfilename + 5 >= sizeof(filename)) + return NULL; + strncpy(filename, cssfilename, pPeriod - cssfilename + 1); + strcpy(filename + (pPeriod - cssfilename + 1), "lock"); + _ds_prepare_path_for(filename); + + lockfile = fopen(filename, "a"); + if (lockfile == NULL) { + LOG(LOG_ERR, ERR_IO_FILE_OPEN, filename, strerror(errno)); + return NULL; + } + r = _ds_get_fcntl_lock(fileno(lockfile)); + if (r) { + fclose(lockfile); + lockfile = NULL; + LOG(LOG_ERR, ERR_IO_LOCK, filename, r, strerror(errno)); + } + return lockfile; +} + +int +_hash_tools_lock_free ( + const char *cssfilename, + FILE* lockfile) +{ + int r; + + if (cssfilename == NULL || lockfile == NULL) + return 0; + + r = _ds_free_fcntl_lock(fileno(lockfile)); + if (!r) { + fclose(lockfile); + } else { + LOG(LOG_ERR, ERR_IO_LOCK_FREE, cssfilename, r, strerror(errno)); + } + + return r; +} + int _hash_drv_open( const char *filename, hash_drv_map_t map, @@ -490,7 +541,7 @@ else _ds_userdir_path(db, CTX->home, CTX->group, "css"); - lock_result = _hash_drv_lock_get (CTX->home, s, + lock_result = _hash_drv_lock_get (CTX, s, (CTX->group) ? CTX->group : CTX->username); if (lock_result < 0) goto BAIL; diff -Nru dspam-3.8.0.orig/src/hash_drv.h dspam-3.8.0/src/hash_drv.h --- dspam-3.8.0.orig/src/hash_drv.h 2007-12-09 13:24:55.000000000 +0200 +++ dspam-3.8.0/src/hash_drv.h 2007-12-09 13:25:46.000000000 +0200 @@ -88,7 +88,7 @@ (DSPAM_CTX * CTX); int _hash_drv_lock_get ( - const char *home, + DSPAM_CTX *CTX, struct _hash_drv_storage *s, const char *username); @@ -96,6 +96,13 @@ struct _hash_drv_storage *s, const char *username); +/* lock variant used by css tools */ +FILE* _hash_tools_lock_get (const char *cssfilename); + +int _hash_tools_lock_free ( + const char *cssfilename, + FILE* lockfile); + int _hash_drv_open( const char *filename, hash_drv_map_t map, diff -Nru dspam-3.8.0.orig/src/tools.hash_drv/cssclean.c dspam-3.8.0/src/tools.hash_drv/cssclean.c --- dspam-3.8.0.orig/src/tools.hash_drv/cssclean.c 2007-12-09 13:24:55.000000000 +0200 +++ dspam-3.8.0/src/tools.hash_drv/cssclean.c 2007-12-09 13:15:22.000000000 +0200 @@ -97,14 +97,13 @@ int cssclean(const char *filename) { int i; hash_drv_header_t header; - struct _hash_drv_storage s; + FILE* lockfile; void *offset; struct _hash_drv_map old, new; hash_drv_spam_record_t rec; unsigned long filepos; - char newfile[PATH_MAX]; - char *oldfile; - char *home, *username; + char *dir = NULL; + char *newfile = NULL; struct stat st; unsigned long hash_rec_max = HASH_REC_MAX; @@ -138,51 +137,46 @@ if (READ_ATTRIB("HashMaxSeek")) max_seek = strtol(READ_ATTRIB("HashMaxSeek"), NULL, 0); - oldfile = strdup(filename); - if (!oldfile) + if (stat(filename, &st) < 0) return EFAILURE; - oldfile = dirname(oldfile); /* oldfile may not be free'd now */ - snprintf(newfile, sizeof(newfile), "%s/%u.css", oldfile, (unsigned int) getpid()); - /* set home and username */ - username = strdup(oldfile); - home = strdup(oldfile); - if (!username || !home) - return EFAILURE; - username = basename(username); /* username may not be free'd now */ - home = dirname(home); /* home may not be free'd now */ - /* make sure at least /two/dirs/to.css for sane operation */ - if (!strcmp(username, home)) + /* create a temporary file name */ + dir = strdup(filename); + if (dir == NULL) return EFAILURE; - - if (stat(filename, &st) < 0) + newfile = tempnam(dirname(dir), "css"); + if (newfile == NULL) return EFAILURE; - if (_hash_drv_lock_get (home, &s, username) < 0) + lockfile = _hash_tools_lock_get (filename); + if (lockfile == NULL) return EFAILURE; if (_hash_drv_open(filename, &old, 0, max_seek, max_extents, extent_size, pctincrease, flags)) - goto unlock; + goto end; if (_hash_drv_open(newfile, &new, hash_rec_max, max_seek, max_extents, extent_size, pctincrease, flags)) { _hash_drv_close(&old); - goto unlock; + goto end; } + + /* preserve counters */ + memcpy(new.header, old.header, sizeof(*new.header)); if (fchown(new.fd, st.st_uid, st.st_gid) < 0) { _hash_drv_close(&new); _hash_drv_close(&old); unlink(newfile); - goto unlock; + goto end; } if (fchmod(new.fd, st.st_mode) < 0) { _hash_drv_close(&new); _hash_drv_close(&old); unlink(newfile); - goto unlock; + goto end; } filepos = sizeof(struct _hash_drv_header); @@ -196,7 +190,7 @@ _hash_drv_close(&new); _hash_drv_close(&old); unlink(newfile); - goto unlock; + goto end; } } filepos += sizeof(struct _hash_drv_spam_record); @@ -209,11 +203,15 @@ _hash_drv_close(&new); _hash_drv_close(&old); if (rename(newfile, filename) < 0) - goto unlock; + goto end; rc = 0; -unlock: - _hash_drv_lock_free(&s, username); +end: + if (dir) + free(dir); + if (newfile) + free(newfile); + _hash_tools_lock_free(filename, lockfile); return rc; }