/* * create_db.c - Part of AFD, an automatic file distribution program. * Copyright (c) 1995 - 2023 Holger Kiehl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "afddefs.h" DESCR__S_M3 /* ** NAME ** create_db - creates structure instant_db and initialises it ** for dir_check ** ** SYNOPSIS ** int create_db(FILE *udc_reply_fp) ** ** DESCRIPTION ** This function creates structure instant_db and initialises it ** with data from the shared memory area created by the AMG. See ** amgdefs.h for a more detailed description of structure instant_db. ** ** RETURN VALUES ** Will exit with INCORRECT when itt encounters an error. On success ** it will return the number of jobs it has found in the shared ** memory area. ** ** AUTHOR ** H.Kiehl ** ** HISTORY ** 01.10.1995 H.Kiehl Created ** 02.01.1997 H.Kiehl Added logging of file names that are found by ** by the AFD. ** 01.02.1997 H.Kiehl Read renaming rule file. ** 19.04.1997 H.Kiehl Add support for writing messages in one memory ** mapped file. ** 26.10.1997 H.Kiehl If disk is full do not give up. ** 21.01.1998 H.Kiehl Rewrite to accommodate new messages and job ID's. ** 14.08.2000 H.Kiehl File mask no longer a fixed array. ** 04.01.2001 H.Kiehl Check for duplicate paused directories. ** 05.04.2001 H.Kiehl Remove O_TRUNC. ** 25.04.2001 H.Kiehl Rename files from pool directory if there is only ** one job for this directory. ** 16.05.2002 H.Kiehl Removed shared memory stuff. ** 30.10.2002 H.Kiehl Take afd_file_dir as the directory to determine ** if we can just move a file. ** 28.02.2003 H.Kiehl Added option grib2wmo. ** 13.07.2003 H.Kiehl Option "age-limit" is now used by AMG as well. ** 24.06.2006 H.Kiehl Allow for duplicate directories when the ** directories are in different DIR_CONFIGS. ** 11.05.2017 H.Kiehl Use update_db_log() when printing errrors so ** one sees them with udc. ** */ DESCR__E_M3 #include /* fprintf(), snprintf() */ #include /* strcpy(), strcat(), strcmp(), */ /* memcpy(), strerror(), strlen() */ #include /* atoi(), calloc(), malloc(), free(),*/ /* exit() */ #include /* isdigit() */ #include /* time() */ #include #ifdef HAVE_STATX # include /* makedev() */ #endif #include #ifdef HAVE_MMAP # include /* msync(), munmap() */ #endif #ifdef HAVE_FCNTL_H # include #endif #include /* fork(), rmdir(), fstat() */ #include #include "amgdefs.h" #include "version.h" /* External global variables. */ extern int fsa_fd, no_fork_jobs, no_of_hosts, no_of_local_dirs, no_of_time_jobs, #ifdef MULTI_FS_SUPPORT no_of_extra_work_dirs, #else outgoing_file_dir_length, #endif *time_job_list; extern unsigned int default_age_limit; #ifdef _DISTRIBUTION_LOG extern unsigned int max_jobs_per_file; #endif extern off_t amg_data_size; extern char *afd_file_dir, #ifndef MULTI_FS_SUPPORT outgoing_file_dir[], time_dir[], #endif *p_mmap, *p_work_dir; #ifdef _WITH_PTHREAD extern struct data_t *p_data; #else extern unsigned int max_file_buffer; #endif #ifdef MULTI_FS_SUPPORT extern struct extra_work_dirs *ewl; #endif extern struct fork_job_data *fjd; extern struct directory_entry *de; extern struct instant_db *db; extern struct afd_status *p_afd_status; extern struct filetransfer_status *fsa; extern struct fileretrieve_status *fra; #ifdef _DISTRIBUTION_LOG extern struct file_dist_list **file_dist_pool; #endif /* Global variables. */ int dnb_fd, fmd_fd = -1, /* File Mask Database fd. */ jd_fd, *no_of_passwd, pwb_fd, *no_of_dir_names, *no_of_job_ids; off_t fmd_size = 0; char *fmd, *fmd_end, #ifdef WITH_GOTCHA_LIST *gotcha = NULL, #endif msg_dir[MAX_PATH_LENGTH], *p_msg_dir; struct job_id_data *jd; struct dir_name_buf *dnb; struct passwd_buf *pwb; /* Local function prototypes. */ #ifdef MULTI_FS_SUPPORT static int check_extra_filesystem(dev_t, int); #endif static void send_busy_working(int), write_current_job_list(int); /* #define _WITH_JOB_LIST_TEST 1 */ #define POS_STEP_SIZE 20 #define FORK_JOB_STEP_SIZE 20 /*+++++++++++++++++++++++++++++ create_db() +++++++++++++++++++++++++++++*/ int create_db(FILE *udc_reply_fp, int write_fd) { int amg_data_fd, exec_flag, exec_flag_dir, i, j, #if defined (_TEST_FILE_TABLE) || defined (_DISTRIBUTION_LOG) k, #endif not_in_same_file_system = 0, one_job_only_dir = 0, show_one_job_no_link, size, dir_counter = 0, no_of_jobs; unsigned int jid_number, scheme; #ifdef WITH_ERROR_QUEUE int no_of_cids; unsigned int *cml; #endif #ifdef _DISTRIBUTION_LOG unsigned int max_jobs_per_dir; #endif dev_t current_dir_dev, ldv; /* Local device number (filesystem). */ time_t start_time; char amg_data_file[MAX_PATH_LENGTH], *ptr, *tmp_ptr, *p_offset, *p_loptions, *p_file; struct p_array *p_ptr; #ifdef HAVE_STATX struct statx stat_buf; #else struct stat stat_buf; #endif /* Check if we need to free some data. */ if (fjd != NULL) { free(fjd); fjd = NULL; no_fork_jobs = 0; } if (db != NULL) { if (p_mmap != NULL) { ptr = p_mmap; no_of_jobs = *(int *)ptr; } else { no_of_jobs = 0; } for (i = 0; i < no_of_jobs; i++) { if (db[i].te != NULL) { free(db[i].te); db[i].te = NULL; } } free(db); db = NULL; /* Lets just assume that when db was allocated that the data */ /* in struct directory_entry is also still allocated. */ #ifdef WITH_ONETIME for (i = 0; i < (no_of_local_dirs + MAX_NO_OF_ONETIME_DIRS); i++) #else for (i = 0; i < no_of_local_dirs; i++) #endif { for (j = 0; j < de[i].nfg; j++) { free(de[i].fme[j].pos); de[i].fme[j].pos = NULL; free(de[i].fme[j].file_mask); de[i].fme[j].file_mask = NULL; } free(de[i].fme); de[i].fme = NULL; de[i].nfg = 0; if (de[i].paused_dir != NULL) { free(de[i].paused_dir); de[i].paused_dir = NULL; } if (de[i].rl_fd != -1) { if (close(de[i].rl_fd) == -1) { system_log(DEBUG_SIGN, __FILE__, __LINE__, "Failed to close() retrieve list file for directory ID %x: %s", de[i].dir_id, strerror(errno)); } de[i].rl_fd = -1; } if (de[i].rl != NULL) { ptr = (char *)de[i].rl - AFD_WORD_OFFSET; if (munmap(ptr, de[i].rl_size) == -1) { system_log(WARN_SIGN, __FILE__, __LINE__, "Failed to munmap() from retrieve list file for directory ID %x: %s", de[i].dir_id, strerror(errno)); } de[i].rl = NULL; } } } if (p_mmap != NULL) { #ifdef HAVE_MMAP if (munmap(p_mmap, amg_data_size) == -1) #else if (munmap_emu((void *)p_mmap) == -1) #endif { system_log(WARN_SIGN, __FILE__, __LINE__, "Failed to munmap() from %s : %s", AMG_DATA_FILE, strerror(errno)); } p_mmap = NULL; show_one_job_no_link = NO; } else { show_one_job_no_link = YES; } /* Set flag to indicate that we are writting in JID structure. */ if ((p_afd_status->amg_jobs & WRITTING_JID_STRUCT) == 0) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; } /* Get device number for working directory. */ #ifdef HAVE_STATX if (statx(0, afd_file_dir, AT_STATX_SYNC_AS_STAT, 0, &stat_buf) == -1) #else if (stat(afd_file_dir, &stat_buf) == -1) #endif { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, #ifdef HAVE_STATX "Failed to statx() `%s' : %s", #else "Failed to stat() `%s' : %s", #endif afd_file_dir, strerror(errno)); exit(INCORRECT); } #ifdef HAVE_STATX ldv = makedev(stat_buf.stx_dev_major, stat_buf.stx_dev_minor); #else ldv = stat_buf.st_dev; #endif (void)snprintf(amg_data_file, MAX_PATH_LENGTH, "%s%s%s", p_work_dir, FIFO_DIR, AMG_DATA_FILE); if ((amg_data_fd = open(amg_data_file, O_RDWR)) == -1) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to open() `%s' : %s", amg_data_file, strerror(errno)); exit(INCORRECT); } #ifdef HAVE_STATX if (statx(amg_data_fd, "", AT_STATX_SYNC_AS_STAT | AT_EMPTY_PATH, STATX_SIZE, &stat_buf) == -1) #else if (fstat(amg_data_fd, &stat_buf) == -1) #endif { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, #ifdef HAVE_STATX "Failed to statx() `%s' : %s", #else "Failed to fstat() `%s' : %s", #endif amg_data_file, strerror(errno)); exit(INCORRECT); } #ifdef HAVE_STATX amg_data_size = stat_buf.stx_size; #else amg_data_size = stat_buf.st_size; #endif #ifdef HAVE_MMAP if ((p_mmap = mmap(NULL, amg_data_size, (PROT_READ | PROT_WRITE), MAP_SHARED, amg_data_fd, 0)) == (caddr_t) -1) #else if ((p_mmap = mmap_emu(NULL, amg_data_size, (PROT_READ | PROT_WRITE), MAP_SHARED, amg_data_file, 0)) == (caddr_t) -1) #endif { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to mmap() `%s' : %s", amg_data_file, strerror(errno)); exit(INCORRECT); } if (close(amg_data_fd) == -1) { system_log(DEBUG_SIGN, __FILE__, __LINE__, "close() error : %s", strerror(errno)); } ptr = p_mmap; /* First get the no of jobs. */ no_of_jobs = *(int *)ptr; ptr += sizeof(int); /* Allocate some memory to store instant database. */ if ((db = malloc(no_of_jobs * sizeof(struct instant_db))) == NULL) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "malloc() error : %s", strerror(errno)); exit(INCORRECT); } init_job_data(); #ifdef WITH_GOTCHA_LIST /* Allocate space for the gotchas. */ size = ((*no_of_job_ids / JOB_ID_DATA_STEP_SIZE) + 1) * JOB_ID_DATA_STEP_SIZE * sizeof(char); if ((gotcha = malloc(size)) == NULL) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to malloc() memory : %s", strerror(errno)); exit(INCORRECT); } # ifdef _WITH_JOB_LIST_TEST { int changed = 0; for (i = 0; i < size; i++) { if (changed < 7) { gotcha[i] = YES; changed = 0; } else { gotcha[i] = NO; } changed++; } } # else (void)memset(gotcha, NO, size); # endif #endif if (no_of_time_jobs > 0) { no_of_time_jobs = 0; free(time_job_list); time_job_list = NULL; } #ifdef _DISTRIBUTION_LOG max_jobs_per_file = 0; max_jobs_per_dir = 0; #endif /* Create and copy pointer array. */ size = no_of_jobs * sizeof(struct p_array); if ((tmp_ptr = calloc(no_of_jobs, sizeof(struct p_array))) == NULL) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Could not allocate memory : %s", strerror(errno)); exit(INCORRECT); } p_ptr = (struct p_array *)tmp_ptr; memcpy(p_ptr, ptr, size); p_offset = ptr + size; de[0].nfg = 0; de[0].fme = NULL; de[0].flag = 0; de[0].dir = p_ptr[0].ptr[DIRECTORY_PTR_POS] + p_offset; de[0].alias = p_ptr[0].ptr[ALIAS_NAME_PTR_POS] + p_offset; if ((de[0].fra_pos = lookup_fra_pos(de[0].alias)) == INCORRECT) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to locate dir alias `%s' for directory `%s'", de[0].alias, de[0].dir); exit(INCORRECT); } de[0].dir_id = fra[de[0].fra_pos].dir_id; de[0].search_time = 0; if ((fra[de[0].fra_pos].fsa_pos != -1) && (fra[de[0].fra_pos].fsa_pos < no_of_hosts)) { size_t length; length = strlen(de[0].dir) + 1 + 1 + strlen(fsa[fra[de[0].fra_pos].fsa_pos].host_alias) + 1; if ((de[0].paused_dir = malloc(length)) == NULL) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to malloc() %d bytes : %s", length, strerror(errno)); exit(INCORRECT); } (void)snprintf(de[0].paused_dir, length, "%s/.%s", de[0].dir, fsa[fra[de[0].fra_pos].fsa_pos].host_alias); } else { de[0].paused_dir = NULL; } #ifdef HAVE_STATX if (statx(0, de[0].dir, AT_STATX_SYNC_AS_STAT, 0, &stat_buf) < 0) { system_log(ERROR_SIGN, __FILE__, __LINE__, "Failed to statx() `%s' : %s", de[0].dir, strerror(errno)); current_dir_dev = ldv + 1; } else { current_dir_dev = makedev(stat_buf.stx_dev_major, stat_buf.stx_dev_minor); } #else if (stat(de[0].dir, &stat_buf) < 0) { system_log(ERROR_SIGN, __FILE__, __LINE__, "Failed to stat() `%s' : %s", de[0].dir, strerror(errno)); current_dir_dev = ldv + 1; } else { current_dir_dev = stat_buf.st_dev; } #endif #ifdef MULTI_FS_SUPPORT de[0].dev = current_dir_dev; #endif if (current_dir_dev != ldv) { #ifdef MULTI_FS_SUPPORT if (check_extra_filesystem(de[0].dev, 0) == YES) { de[0].flag |= IN_SAME_FILESYSTEM; } else { #endif #ifdef _MAINTAINER_LOG maintainer_log(INFO_SIGN, NULL, 0, "%s not in same filesystem", db[0].dir); #endif not_in_same_file_system++; #ifdef MULTI_FS_SUPPORT } #endif } else { de[0].flag |= IN_SAME_FILESYSTEM; #ifdef MULTI_FS_SUPPORT de[0].ewl_pos = 0; #endif } if (((no_of_jobs - 1) == 0) || (de[0].dir != (p_ptr[1].ptr[DIRECTORY_PTR_POS] + p_offset))) { de[0].flag |= RENAME_ONE_JOB_ONLY; one_job_only_dir++; } start_time = time(NULL); exec_flag_dir = 0; for (i = 0; i < no_of_jobs; i++) { #ifdef _DISTRIBUTION_LOG max_jobs_per_dir += 1; #endif exec_flag = 0; /* Store DIR_CONFIG ID. */ db[i].dir_config_id = (unsigned int)strtoul(p_ptr[i].ptr[DIR_CONFIG_ID_PTR_POS] + p_offset, NULL, 16); /* Store directory pointer. */ db[i].dir = p_ptr[i].ptr[DIRECTORY_PTR_POS] + p_offset; /* Store priority. */ db[i].priority = *(p_ptr[i].ptr[PRIORITY_PTR_POS] + p_offset); /* Store number of files to be send. */ db[i].no_of_files = atoi(p_ptr[i].ptr[NO_OF_FILES_PTR_POS] + p_offset); /* Store pointer to first file (filter). */ db[i].files = p_ptr[i].ptr[FILE_PTR_POS] + p_offset; /* * Store all file names of one directory into one array. This * is necessary so we can specify overlapping wild cards in * different file sections for one directory section. */ if ((i > 0) && (db[i].dir != db[i - 1].dir)) { if ((de[dir_counter].flag & DELETE_ALL_FILES) || ((de[dir_counter].flag & IN_SAME_FILESYSTEM) && (exec_flag_dir == 0))) { if ((fra[de[dir_counter].fra_pos].dir_flag & LINK_NO_EXEC) == 0) { fra[de[dir_counter].fra_pos].dir_flag |= LINK_NO_EXEC; } } else { if (fra[de[dir_counter].fra_pos].dir_flag & LINK_NO_EXEC) { fra[de[dir_counter].fra_pos].dir_flag ^= LINK_NO_EXEC; } } #ifdef _DISTRIBUTION_LOG if (max_jobs_per_dir > max_jobs_per_file) { max_jobs_per_file = max_jobs_per_dir; } max_jobs_per_dir = 0; #endif exec_flag_dir = 0; dir_counter++; if (dir_counter >= no_of_local_dirs) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Aaarghhh, dir_counter (%d) >= no_of_local_dirs (%d)!?", dir_counter, no_of_local_dirs); exit(INCORRECT); } de[dir_counter].dir = db[i].dir; de[dir_counter].alias = p_ptr[i].ptr[ALIAS_NAME_PTR_POS] + p_offset; if ((de[dir_counter].fra_pos = lookup_fra_pos(de[dir_counter].alias)) == INCORRECT) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to locate dir alias `%s' for directory `%s'", de[dir_counter].alias, de[dir_counter].dir); exit(INCORRECT); } de[dir_counter].dir_id = fra[de[dir_counter].fra_pos].dir_id; de[dir_counter].nfg = 0; de[dir_counter].fme = NULL; de[dir_counter].flag = 0; de[dir_counter].search_time = 0; if ((fra[de[dir_counter].fra_pos].fsa_pos != -1) && (fra[de[dir_counter].fra_pos].fsa_pos < no_of_hosts)) { size_t length; length = strlen(de[dir_counter].dir) + 1 + 1 + strlen(fsa[fra[de[dir_counter].fra_pos].fsa_pos].host_alias) + 1; if ((de[dir_counter].paused_dir = malloc(length)) == NULL) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to malloc() %d bytes : %s", length, strerror(errno)); exit(INCORRECT); } (void)snprintf(de[dir_counter].paused_dir, length, "%s/.%s", de[dir_counter].dir, fsa[fra[de[dir_counter].fra_pos].fsa_pos].host_alias); } else { de[dir_counter].paused_dir = NULL; } #ifdef HAVE_STATX if (statx(0, db[i].dir, AT_STATX_SYNC_AS_STAT, 0, &stat_buf) < 0) #else if (stat(db[i].dir, &stat_buf) < 0) #endif { system_log(ERROR_SIGN, __FILE__, __LINE__, #ifdef HAVE_STATX "Failed to statx() `%s' (i=%d) : %s", #else "Failed to stat() `%s' (i=%d) : %s", #endif db[i].dir, i, strerror(errno)); current_dir_dev = ldv + 1; } else { #ifdef HAVE_STATX current_dir_dev = makedev(stat_buf.stx_dev_major, stat_buf.stx_dev_minor); #else current_dir_dev = stat_buf.st_dev; #endif } #ifdef MULTI_FS_SUPPORT de[dir_counter].dev = current_dir_dev; #endif if (current_dir_dev != ldv) { #ifdef MULTI_FS_SUPPORT if (check_extra_filesystem(current_dir_dev, dir_counter) == YES) { de[dir_counter].flag |= IN_SAME_FILESYSTEM; } else { #endif #ifdef _MAINTAINER_LOG maintainer_log(INFO_SIGN, NULL, 0, "%s not in same filesystem", de[dir_counter].dir); #endif not_in_same_file_system++; #ifdef MULTI_FS_SUPPORT } #endif } else { de[dir_counter].flag |= IN_SAME_FILESYSTEM; #ifdef MULTI_FS_SUPPORT de[dir_counter].ewl_pos = 0; #endif } if ((i == (no_of_jobs - 1)) || (db[i].dir != (p_ptr[i + 1].ptr[DIRECTORY_PTR_POS] + p_offset))) { de[dir_counter].flag |= RENAME_ONE_JOB_ONLY; one_job_only_dir++; } } db[i].fra_pos = de[dir_counter].fra_pos; db[i].dir_id = de[dir_counter].dir_id; #ifdef MULTI_FS_SUPPORT db[i].ewl_pos = de[dir_counter].ewl_pos; #endif /* * Check if this directory is in the same file system * as file directory of the AFD. If this is not the case * lets fork when we copy. */ db[i].lfs = 0; #ifdef MULTI_FS_SUPPORT if (de[dir_counter].flag & IN_SAME_FILESYSTEM) { db[i].lfs |= IN_SAME_FILESYSTEM; } #else if (current_dir_dev == ldv) { db[i].lfs |= IN_SAME_FILESYSTEM; } #endif if ((i == 0) || ((i > 0) && (db[i].files != db[i - 1].files))) { if ((de[dir_counter].nfg % FG_BUFFER_STEP_SIZE) == 0) { char *ptr_start; size_t new_size; /* Calculate new size of file group buffer. */ new_size = ((de[dir_counter].nfg / FG_BUFFER_STEP_SIZE) + 1) * FG_BUFFER_STEP_SIZE * sizeof(struct file_mask_entry); if ((de[dir_counter].fme = realloc(de[dir_counter].fme, new_size)) == NULL) { system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to realloc() %d bytes : %s", new_size, strerror(errno)); p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; unmap_data(jd_fd, (void *)&jd); exit(INCORRECT); } /* Initialise new memory area. */ if (de[dir_counter].nfg > (FG_BUFFER_STEP_SIZE - 1)) { ptr_start = (char *)(de[dir_counter].fme) + (de[dir_counter].nfg * sizeof(struct file_mask_entry)); } else { ptr_start = (char *)de[dir_counter].fme; } (void)memset(ptr_start, 0, (FG_BUFFER_STEP_SIZE * sizeof(struct file_mask_entry))); } p_file = db[i].files; de[dir_counter].fme[de[dir_counter].nfg].nfm = db[i].no_of_files; if ((de[dir_counter].fme[de[dir_counter].nfg].file_mask = malloc((db[i].no_of_files * sizeof(char *)))) == NULL) { system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to malloc() %d bytes : %s", db[i].no_of_files * sizeof(char *), strerror(errno)); p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; unmap_data(jd_fd, (void *)&jd); exit(INCORRECT); } de[dir_counter].fme[de[dir_counter].nfg].dest_count = 0; for (j = 0; j < db[i].no_of_files; j++) { de[dir_counter].fme[de[dir_counter].nfg].file_mask[j] = p_file; if ((p_file[0] == '*') && (p_file[1] == '\0')) { de[dir_counter].flag |= ALL_FILES; } NEXT(p_file); } db[i].fbl = p_file - db[i].files; lookup_file_mask_id(&db[i], db[i].fbl); if ((de[dir_counter].flag & ALL_FILES) && (db[i].no_of_files > 1)) { p_file = db[i].files; for (j = 0; j < db[i].no_of_files; j++) { if (p_file[0] == '!') { de[dir_counter].flag ^= ALL_FILES; break; } NEXT(p_file); } } if ((de[dir_counter].fme[de[dir_counter].nfg].dest_count % POS_STEP_SIZE) == 0) { size_t new_size; /* Calculate new size of file group buffer. */ new_size = ((de[dir_counter].fme[de[dir_counter].nfg].dest_count / POS_STEP_SIZE) + 1) * POS_STEP_SIZE * sizeof(int); if ((de[dir_counter].fme[de[dir_counter].nfg].pos = realloc(de[dir_counter].fme[de[dir_counter].nfg].pos, new_size)) == NULL) { system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to realloc() %d bytes : %s", new_size, strerror(errno)); p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; unmap_data(jd_fd, (void *)&jd); exit(INCORRECT); } } de[dir_counter].fme[de[dir_counter].nfg].pos[de[dir_counter].fme[de[dir_counter].nfg].dest_count] = i; de[dir_counter].fme[de[dir_counter].nfg].dest_count++; de[dir_counter].nfg++; #ifdef _DISTRIBUTION_LOG if (de[dir_counter].nfg > max_jobs_per_file) { max_jobs_per_file = de[dir_counter].nfg; } #endif } else if ((i > 0) && (db[i].files == db[i - 1].files)) { if ((de[dir_counter].fme[de[dir_counter].nfg - 1].dest_count % POS_STEP_SIZE) == 0) { size_t new_size; /* Calculate new size of file group buffer. */ new_size = ((de[dir_counter].fme[de[dir_counter].nfg - 1].dest_count / POS_STEP_SIZE) + 1) * POS_STEP_SIZE * sizeof(int); if ((de[dir_counter].fme[de[dir_counter].nfg - 1].pos = realloc(de[dir_counter].fme[de[dir_counter].nfg - 1].pos, new_size)) == NULL) { system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to realloc() %d bytes : %s", new_size, strerror(errno)); p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; unmap_data(jd_fd, (void *)&jd); exit(INCORRECT); } } de[dir_counter].fme[de[dir_counter].nfg - 1].pos[de[dir_counter].fme[de[dir_counter].nfg - 1].dest_count] = i; de[dir_counter].fme[de[dir_counter].nfg - 1].dest_count++; db[i].file_mask_id = db[i - 1].file_mask_id; db[i].fbl = db[i - 1].fbl; } /* Store number of local options. */ db[i].no_of_loptions = atoi(p_ptr[i].ptr[NO_LOCAL_OPTIONS_PTR_POS] + p_offset); db[i].next_start_time = 0; db[i].time_option_type = NO_TIME; db[i].no_of_time_entries = 0; db[i].te = NULL; /* Store pointer to first local option. */ if (db[i].no_of_loptions > 0) { db[i].loptions = p_ptr[i].ptr[LOCAL_OPTIONS_PTR_POS] + p_offset; db[i].loptions_flag = (unsigned int)strtoul(p_ptr[i].ptr[LOCAL_OPTIONS_FLAG_PTR_POS] + p_offset, NULL, 16); /* * Because some options (such as exec, extracting bulletins, etc.) * can take a while, it is better to fork such jobs. We can do this * by setting the lfs flag to GO_PARALLEL. */ p_loptions = db[i].loptions; db[i].timezone[0] = '\0'; for (j = 0; j < db[i].no_of_loptions; j++) { if (db[i].loptions_flag & DELETE_ID_FLAG) { db[i].lfs = DELETE_ALL_FILES; break; } if ((db[i].loptions_flag & EXEC_ID_FLAG) && (CHECK_STRNCMP(p_loptions, EXEC_ID, EXEC_ID_LENGTH) == 0)) { db[i].lfs |= GO_PARALLEL; db[i].lfs |= DO_NOT_LINK_FILES; exec_flag = 1; exec_flag_dir = 1; } #ifdef WITH_TIMEZONE else if ((db[i].loptions_flag & TIMEZONE_ID_FLAG) && (CHECK_STRNCMP(p_loptions, TIMEZONE_ID, TIMEZONE_ID_LENGTH) == 0)) { int length = 0; char *ptr = p_loptions + TIMEZONE_ID_LENGTH; while ((*ptr == ' ') || (*ptr == '\t')) { ptr++; } while ((length < MAX_TIMEZONE_LENGTH) && (*ptr != '\n') && (*ptr != '\0')) { db[i].timezone[length] = *ptr; ptr++; length++; } if ((length > 0) && (length != MAX_TIMEZONE_LENGTH)) { db[i].timezone[length] = '\0'; } else { db[i].timezone[0] = '\0'; update_db_log(WARN_SIGN, __FILE__, __LINE__, udc_reply_fp, NULL, "Unable to store the timezone `%s', since we can only store %d bytes. Please contact maintainer (%s) if this is a valid timezone.", p_loptions + TIMEZONE_ID_LENGTH + 1, MAX_TIMEZONE_LENGTH, AFD_MAINTAINER); } } #endif else if ((db[i].loptions_flag & TIME_NO_COLLECT_ID_FLAG) && (CHECK_STRNCMP(p_loptions, TIME_NO_COLLECT_ID, TIME_NO_COLLECT_ID_LENGTH) == 0)) { char *ptr = p_loptions + TIME_NO_COLLECT_ID_LENGTH; struct bd_time_entry te; while ((*ptr == ' ') || (*ptr == '\t')) { ptr++; } if (eval_time_str(ptr, &te, udc_reply_fp) == SUCCESS) { int new_size; struct bd_time_entry *tmp_te; new_size = (db[i].no_of_time_entries + 1) * sizeof(struct bd_time_entry); if ((tmp_te = realloc(db[i].te, new_size)) == NULL) { system_log(ERROR_SIGN, __FILE__, __LINE__, "Failed to realloc() %d bytes : %s", new_size, strerror(errno)); } else { db[i].te = tmp_te; db[i].time_option_type = SEND_NO_COLLECT_TIME; (void)memcpy(&db[i].te[db[i].no_of_time_entries], &te, sizeof(struct bd_time_entry)); db[i].no_of_time_entries++; } } else { update_db_log(ERROR_SIGN, __FILE__, __LINE__, udc_reply_fp, NULL, "%s", ptr); } } else if ((db[i].loptions_flag & TIME_ID_FLAG) && (CHECK_STRNCMP(p_loptions, TIME_ID, TIME_ID_LENGTH) == 0)) { char *ptr = p_loptions + TIME_ID_LENGTH; struct bd_time_entry te; while ((*ptr == ' ') || (*ptr == '\t')) { ptr++; } if (eval_time_str(ptr, &te, udc_reply_fp) == SUCCESS) { int new_size; struct bd_time_entry *tmp_te; new_size = (db[i].no_of_time_entries + 1) * sizeof(struct bd_time_entry); if ((tmp_te = realloc(db[i].te, new_size)) == NULL) { system_log(ERROR_SIGN, __FILE__, __LINE__, "Failed to realloc() %d bytes : %s", new_size, strerror(errno)); } else { db[i].te = tmp_te; (void)memcpy(&db[i].te[db[i].no_of_time_entries], &te, sizeof(struct bd_time_entry)); db[i].no_of_time_entries++; db[i].time_option_type = SEND_COLLECT_TIME; } } else { update_db_log(ERROR_SIGN, __FILE__, __LINE__, udc_reply_fp, NULL, "%s", ptr); } } else if ((db[i].loptions_flag & CONVERT_ID_FLAG) && (CHECK_STRNCMP(p_loptions, CONVERT_ID, CONVERT_ID_LENGTH) == 0)) { db[i].lfs |= GO_PARALLEL; db[i].lfs |= DO_NOT_LINK_FILES; } else if ((db[i].loptions_flag & GTS2TIFF_ID_FLAG) && (CHECK_STRNCMP(p_loptions, GTS2TIFF_ID, GTS2TIFF_ID_LENGTH) == 0)) { db[i].lfs |= GO_PARALLEL; } else if ((db[i].loptions_flag & GRIB2WMO_ID_FLAG) && (CHECK_STRNCMP(p_loptions, GRIB2WMO_ID, GRIB2WMO_ID_LENGTH) == 0)) { db[i].lfs |= GO_PARALLEL; } #ifdef _WITH_AFW2WMO else if ((db[i].loptions_flag & AFW2WMO_ID_FLAG) && (CHECK_STRNCMP(p_loptions, AFW2WMO_ID, AFW2WMO_ID_LENGTH) == 0)) { db[i].lfs |= DO_NOT_LINK_FILES; } #endif else if ((db[i].loptions_flag & EXTRACT_ID_FLAG) && (CHECK_STRNCMP(p_loptions, EXTRACT_ID, EXTRACT_ID_LENGTH) == 0)) { db[i].lfs |= GO_PARALLEL; db[i].lfs |= SPLIT_FILE_LIST; } NEXT(p_loptions); } if ((db[i].no_of_time_entries > 0) && (db[i].time_option_type == SEND_COLLECT_TIME)) { db[i].next_start_time = calc_next_time_array(db[i].no_of_time_entries, db[i].te, #ifdef WITH_TIMEZONE db[i].timezone, #endif time(NULL), __FILE__, __LINE__); } } else { db[i].loptions_flag = 0; db[i].loptions = NULL; } /* * If we have RENAME_ONE_JOB_ONLY and there are options that force * us to link the file, we cannot just rename the files! We must * copy them. Thus we must remove the flag when this is the case. */ if ((i == 0) || ((i > 0) && (db[i].files != db[i - 1].files))) { if ((de[dir_counter].flag & RENAME_ONE_JOB_ONLY) && (db[i].lfs & DO_NOT_LINK_FILES)) { one_job_only_dir--; de[dir_counter].flag &= ~RENAME_ONE_JOB_ONLY; } } /* Store number of standard options. */ db[i].no_of_soptions = atoi(p_ptr[i].ptr[NO_STD_OPTIONS_PTR_POS] + p_offset); /* Store pointer to first local option and age limit. */ if (db[i].no_of_soptions > 0) { char *sptr; db[i].soptions = p_ptr[i].ptr[STD_OPTIONS_PTR_POS] + p_offset; if ((sptr = lposi(db[i].soptions, AGE_LIMIT_ID, AGE_LIMIT_ID_LENGTH)) != NULL) { int count = 0; char str_number[MAX_INT_LENGTH]; while ((*sptr == ' ') || (*sptr == '\t')) { sptr++; } while ((*sptr != '\n') && (*sptr != '\0')) { str_number[count] = *sptr; count++; sptr++; } str_number[count] = '\0'; errno = 0; db[i].age_limit = (unsigned int)strtoul(str_number, (char **)NULL, 10); if (errno == ERANGE) { update_db_log(WARN_SIGN, __FILE__, __LINE__, udc_reply_fp, NULL, "Option %s for directory `%s' out of range, resetting to default %u.", AGE_LIMIT_ID, db[i].dir, default_age_limit); db[i].age_limit = default_age_limit; } } else { db[i].age_limit = default_age_limit; } } else { db[i].age_limit = default_age_limit; db[i].soptions = NULL; } /* Store recipient part. */ db[i].recipient = p_ptr[i].ptr[RECIPIENT_PTR_POS] + p_offset; db[i].recipient_id = get_str_checksum(db[i].recipient); scheme = (unsigned int)strtoul((p_ptr[i].ptr[SCHEME_PTR_POS] + p_offset), NULL, 10); db[i].host_alias = p_ptr[i].ptr[HOST_ALIAS_PTR_POS] + p_offset; if ((db[i].position = get_host_position(fsa, db[i].host_alias, no_of_hosts)) < 0) { /* This should be impossible !(?) */ system_log(WARN_SIGN, __FILE__, __LINE__, "Could not locate host `%s' in FSA.", db[i].host_alias); db[i].host_id = get_str_checksum(db[i].host_alias); } else { db[i].host_id = fsa[db[i].position].host_id; } /* * Always check if this directory is not already specified. * This might help to reduce the number of directories that the * function check_paused_dir() has to check. */ db[i].dup_paused_dir = NO; for (j = 0; j < i; j++) { if ((db[j].dir == db[i].dir) && (db[j].host_id == db[i].host_id)) { db[i].dup_paused_dir = YES; break; } } (void)strcpy(db[i].paused_dir, db[i].dir); (void)strcat(db[i].paused_dir, "/."); (void)strcat(db[i].paused_dir, db[i].host_alias); /* Now lets determine what kind of protocol we have here. */ if (scheme & FTP_FLAG) { db[i].protocol = FTP; } else if (scheme & LOC_FLAG) { db[i].protocol = LOC; } else if (scheme & SMTP_FLAG) { db[i].protocol = SMTP; } else if (scheme & SFTP_FLAG) { db[i].protocol = SFTP; } else if (scheme & HTTP_FLAG) { db[i].protocol = HTTP; } else if (scheme & EXEC_FLAG) { db[i].protocol = EXEC; } #ifdef _WITH_SCP_SUPPORT else if (scheme & SCP_FLAG) { db[i].protocol = SCP; } #endif #ifdef _WITH_WMO_SUPPORT else if (scheme & WMO_FLAG) { db[i].protocol = WMO; } #endif #ifdef _WITH_MAP_SUPPORT else if (scheme & MAP_FLAG) { db[i].protocol = MAP; } #endif #ifdef _WITH_DFAX_SUPPORT else if (scheme & DFAX_FLAG) { db[i].protocol = DFAX; } #endif #ifdef _WITH_DE_MAIL_SUPPORT else if (scheme & DE_MAIL_FLAG) { db[i].protocol = DE_MAIL; } #endif else { update_db_log(FATAL_SIGN, __FILE__, __LINE__, udc_reply_fp, NULL, "Unknown sheme in url: `%s'.", db[i].recipient); p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; free(db); free(de); free(tmp_ptr); unmap_data(jd_fd, (void *)&jd); exit(INCORRECT); } #ifdef MULTI_FS_SUPPORT lookup_job_id(&db[i], &jid_number, ewl[de[dir_counter].ewl_pos].outgoing_file_dir, ewl[de[dir_counter].ewl_pos].outgoing_file_dir_length); #else lookup_job_id(&db[i], &jid_number, outgoing_file_dir, outgoing_file_dir_length); #endif if (db[i].time_option_type == SEND_COLLECT_TIME) { enter_time_job(i); } if (exec_flag == 1) { if ((no_fork_jobs % FORK_JOB_STEP_SIZE) == 0) { size_t new_size; new_size = ((no_fork_jobs / FORK_JOB_STEP_SIZE) + 1) * FORK_JOB_STEP_SIZE * sizeof(struct fork_job_data); if ((fjd = realloc(fjd, new_size)) == NULL) { system_log(FATAL_SIGN, __FILE__, __LINE__, "Could not realloc() %d bytes : %s", new_size, strerror(errno)); p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; exit(INCORRECT); } } fjd[no_fork_jobs].forks = 0; fjd[no_fork_jobs].job_id = db[i].job_id; fjd[no_fork_jobs].user_time = 0; fjd[no_fork_jobs].system_time = 0; no_fork_jobs++; } if ((i % 20) == 0) { time_t now = time(NULL); if ((now - start_time) > (JOB_TIMEOUT / 2)) { send_busy_working(write_fd); } } } /* for (i = 0; i < no_of_jobs; i++) */ if ((de[dir_counter].flag & DELETE_ALL_FILES) || ((de[dir_counter].flag & IN_SAME_FILESYSTEM) && (exec_flag_dir == 0))) { if ((fra[de[dir_counter].fra_pos].dir_flag & LINK_NO_EXEC) == 0) { fra[de[dir_counter].fra_pos].dir_flag |= LINK_NO_EXEC; } } else { if (fra[de[dir_counter].fra_pos].dir_flag & LINK_NO_EXEC) { fra[de[dir_counter].fra_pos].dir_flag ^= LINK_NO_EXEC; } } if (no_of_time_jobs > 1) { sort_time_job(); } #ifdef WITH_ERROR_QUEUE if ((cml = malloc(((no_of_jobs + dir_counter) * sizeof(int)))) == NULL) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to malloc() memory : %s", strerror(errno)); exit(INCORRECT); } #endif /* Check for duplicate job entries. */ for (i = 0; i < no_of_jobs; i++) { #ifdef IGNORE_DUPLICATE_JOB_IDS for (j = (i + 1); j < no_of_jobs; j++) { if ((db[i].job_id != 0) && (db[i].job_id == db[j].job_id)) { update_db_log(WARN_SIGN, __FILE__, __LINE__, udc_reply_fp, NULL, "Duplicate job entries for job #%x with directory %s and recipient %s! Will ignore the duplicate entry.", db[i].job_id, db[i].dir, db[i].recipient); db[j].job_id = 0; } } # ifdef WITH_ERROR_QUEUE if (db[i].job_id != 0) { cml[i] = db[i].job_id; } # endif #else for (j = (i + 1); j < no_of_jobs; j++) { if (db[i].job_id == db[j].job_id) { update_db_log(WARN_SIGN, __FILE__, __LINE__, udc_reply_fp, NULL, "Duplicate job entries for job #%x with directory %s and recipient %s!", db[i].job_id, db[i].dir, db[i].recipient); } } # ifdef WITH_ERROR_QUEUE cml[i] = db[i].job_id; # endif #endif } #ifdef WITH_ERROR_QUEUE no_of_cids = i; for (j = 0; j < dir_counter; j++) { if (de[j].paused_dir != NULL) { cml[no_of_cids] = de[j].dir_id; no_of_cids++; } } #endif #ifdef _DISTRIBUTION_LOG if (max_jobs_per_file == 0) { max_jobs_per_file = 1; } j = max_jobs_per_file * sizeof(unsigned int); system_log(DEBUG_SIGN, NULL, 0, "max_jobs_per_file = %u max_file_buffer = %u", max_jobs_per_file, max_file_buffer); # ifdef _WITH_PTHREAD for (m = 0; m < no_of_local_dirs; m++) { for (i = 0; i < fra[m].max_copied_files; i++) { for (k = 0; k < NO_OF_DISTRIBUTION_TYPES; k++) { if (((p_data[m].file_dist_pool[i][k].jid_list = malloc(j)) == NULL) || ((p_data[m].file_dist_pool[i][k].proc_cycles = malloc(max_jobs_per_file)) == NULL)) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "malloc() error : %s", strerror(errno)); exit(INCORRECT); } p_data[m].file_dist_pool[i][k].no_of_dist = 0; } } } # else for (i = 0; i < max_file_buffer; i++) { for (k = 0; k < NO_OF_DISTRIBUTION_TYPES; k++) { if (((file_dist_pool[i][k].jid_list = malloc(j)) == NULL) || ((file_dist_pool[i][k].proc_cycles = malloc(max_jobs_per_file)) == NULL)) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "malloc() error : %s", strerror(errno)); exit(INCORRECT); } file_dist_pool[i][k].no_of_dist = 0; } } # endif #endif /* Write job list file. */ write_current_job_list(no_of_jobs); /* Remove old time job directories. */ #ifdef MULTI_FS_SUPPORT for (i = 0; i < no_of_extra_work_dirs; i++) { if (ewl[i].time_dir != NULL) { check_old_time_jobs(no_of_jobs, ewl[i].time_dir); } } #else check_old_time_jobs(no_of_jobs, time_dir); #endif #ifdef WITH_ERROR_QUEUE /* Validate error queue. */ validate_error_queue(no_of_cids, cml, no_of_hosts, fsa, fsa_fd); free(cml); #endif /* Free all memory. */ free(tmp_ptr); #ifdef WITH_GOTCHA_LIST free(gotcha); gotcha = NULL; #endif unmap_data(dnb_fd, (void *)&dnb); unmap_data(jd_fd, (void *)&jd); unmap_data(fmd_fd, (void *)&fmd); if (pwb != NULL) { unmap_data(pwb_fd, (void *)&pwb); } p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; if (p_afd_status->start_time == 0) { p_afd_status->start_time = time(NULL); } if (show_one_job_no_link == YES) { if (one_job_only_dir > 1) { system_log(DEBUG_SIGN, __FILE__, __LINE__, "%d directories with only one job and no need for linking.", one_job_only_dir); } else if (one_job_only_dir == 1) { system_log(DEBUG_SIGN, __FILE__, __LINE__, "One directory with only one job."); } if (not_in_same_file_system > 1) { update_db_log(INFO_SIGN, __FILE__, __LINE__, udc_reply_fp, NULL, "%d directories not in the same filesystem as AFD.", not_in_same_file_system); } else if (not_in_same_file_system == 1) { update_db_log(INFO_SIGN, __FILE__, __LINE__, udc_reply_fp, NULL, "One directory not in the same filesystem as AFD."); } } #ifdef WITH_ONETIME for (i = (dir_counter + 1); i < (no_of_local_dirs + MAX_NO_OF_ONETIME_DIRS); i++) { de[i].nfg = 0; de[i].fme = NULL; de[i].flag = 0; de[i].dir = NULL; de[i].alias = ; de[i].fra_pos = ; de[i].dir_id = ; de[i].search_time = 0; de[i].paused_dir = NULL; } #endif #ifdef _TEST_FILE_TABLE for (i = 0; i < no_of_local_dirs; i++) { (void)fprintf(stdout, "Directory entry %d : %s\n", i, de[i].dir); for (j = 0; j < de[i].nfg; j++) { (void)fprintf(stdout, "\t%d:\t", j); for (k = 0; k < de[i].fme[j].nfm; k++) { (void)fprintf(stdout, "%s ", de[i].fme[j].file_mask[k]); } (void)fprintf(stdout, "(%d)\n", de[i].fme[j].nfm); (void)fprintf(stdout, "\t\tNumber of destinations = %d\n", de[i].fme[j].dest_count); } (void)fprintf(stdout, "\tNumber of file groups = %d\n", de[i].nfg); if (de[i].flag & ALL_FILES) { (void)fprintf(stdout, "\tAll files selected = YES\n"); } else { (void)fprintf(stdout, "\tAll files selected = NO\n"); } } #endif return(no_of_jobs); } /*+++++++++++++++++++++++++ send_busy_working() +++++++++++++++++++++++++*/ static void send_busy_working(int write_fd) { int action = BUSY_WORKING; if (write(write_fd, &action, 1) != 1) { system_log(WARN_SIGN, __FILE__, __LINE__, "Could not write to fifo %s : %s", DC_RESP_FIFO, strerror(errno)); } return; } /*++++++++++++++++++++++++ write_current_job_list() +++++++++++++++++++++*/ static void write_current_job_list(int no_of_jobs) { int i, fd; unsigned int *int_buf; size_t buf_size; char current_msg_list_file[MAX_PATH_LENGTH]; #ifdef HAVE_STATX struct statx stat_buf; #else struct stat stat_buf; #endif (void)strcpy(current_msg_list_file, p_work_dir); (void)strcat(current_msg_list_file, FIFO_DIR); (void)strcat(current_msg_list_file, CURRENT_MSG_LIST_FILE); /* Overwrite current message list file. */ if ((fd = open(current_msg_list_file, (O_WRONLY | O_CREAT | O_TRUNC), FILE_MODE)) == -1) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to open() `%s' : %s", current_msg_list_file, strerror(errno)); exit(INCORRECT); } #ifdef LOCK_DEBUG lock_region_w(fd, (off_t)0, __FILE__, __LINE__); #else lock_region_w(fd, (off_t)0); #endif /* Create buffer to write ID's in one hunk. */ buf_size = (no_of_jobs + 1) * sizeof(unsigned int); if ((int_buf = malloc(buf_size)) == NULL) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to malloc() %d bytes : %s", buf_size, strerror(errno)); exit(INCORRECT); } int_buf[0] = no_of_jobs; for (i = 0; i < no_of_jobs; i++) { int_buf[i + 1] = db[i].job_id; } if (write(fd, int_buf, buf_size) != buf_size) { p_afd_status->amg_jobs ^= WRITTING_JID_STRUCT; p_afd_status->amg_jobs &= ~REREADING_DIR_CONFIG; system_log(FATAL_SIGN, __FILE__, __LINE__, "Failed to write() to `%s' : %s", current_msg_list_file, strerror(errno)); exit(INCORRECT); } #ifdef HAVE_STATX if (statx(fd, "", AT_STATX_SYNC_AS_STAT | AT_EMPTY_PATH, STATX_SIZE, &stat_buf) == -1) #else if (fstat(fd, &stat_buf) == -1) #endif { system_log(DEBUG_SIGN, __FILE__, __LINE__, #ifdef HAVE_STATX "Failed to statx() `%s' : %s", #else "Failed to fstat() `%s' : %s", #endif current_msg_list_file, strerror(errno)); } else { #ifdef HAVE_STATX if (stat_buf.stx_size > buf_size) #else if (stat_buf.st_size > buf_size) #endif { if (ftruncate(fd, buf_size) == -1) { system_log(WARN_SIGN, __FILE__, __LINE__, "Failed to ftruncate() `%s' to %d bytes : %s", current_msg_list_file, buf_size, strerror(errno)); } } } if (close(fd) == -1) { system_log(DEBUG_SIGN, __FILE__, __LINE__, "close() error : %s", strerror(errno)); } free(int_buf); return; } #ifdef MULTI_FS_SUPPORT /*++++++++++++++++++++++++ check_extra_filesystem() +++++++++++++++++++++*/ static int check_extra_filesystem(dev_t dev, int de_no) { int i; for (i = 0; i < no_of_extra_work_dirs; i++) { if (ewl[i].dev == dev) { if (ewl[i].dir_name == NULL) { de[de_no].ewl_pos = 0; return(NO); } else { de[de_no].ewl_pos = i; return(YES); } } } de[de_no].ewl_pos = 0; return(NO); } #endif /* MULTI_FS_SUPPORT */