1c0b746e5SOllivier Robert /* 2c0b746e5SOllivier Robert * ntp_filegen.c,v 3.12 1994/01/25 19:06:11 kardel Exp 3c0b746e5SOllivier Robert * 4c0b746e5SOllivier Robert * implements file generations support for NTP 5c0b746e5SOllivier Robert * logfiles and statistic files 6c0b746e5SOllivier Robert * 7c0b746e5SOllivier Robert * 8c0b746e5SOllivier Robert * Copyright (C) 1992, 1996 by Rainer Pruy 9c0b746e5SOllivier Robert * Friedrich-Alexander Universit�t Erlangen-N�rnberg, Germany 10c0b746e5SOllivier Robert * 11c0b746e5SOllivier Robert * This code may be modified and used freely 12c0b746e5SOllivier Robert * provided credits remain intact. 13c0b746e5SOllivier Robert */ 14c0b746e5SOllivier Robert 15c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H 16c0b746e5SOllivier Robert #include <config.h> 17c0b746e5SOllivier Robert #endif 18c0b746e5SOllivier Robert 19c0b746e5SOllivier Robert #include <stdio.h> 20c0b746e5SOllivier Robert #include <sys/types.h> 21c0b746e5SOllivier Robert #include <sys/stat.h> 22c0b746e5SOllivier Robert 23c0b746e5SOllivier Robert #include "ntpd.h" 24c0b746e5SOllivier Robert #include "ntp_io.h" 25c0b746e5SOllivier Robert #include "ntp_string.h" 26c0b746e5SOllivier Robert #include "ntp_calendar.h" 27c0b746e5SOllivier Robert #include "ntp_filegen.h" 28c0b746e5SOllivier Robert #include "ntp_stdlib.h" 29c0b746e5SOllivier Robert 30c0b746e5SOllivier Robert /* 31c0b746e5SOllivier Robert * NTP is intended to run long periods of time without restart. 32c0b746e5SOllivier Robert * Thus log and statistic files generated by NTP will grow large. 33c0b746e5SOllivier Robert * 34c0b746e5SOllivier Robert * this set of routines provides a central interface 35c0b746e5SOllivier Robert * to generating files using file generations 36c0b746e5SOllivier Robert * 37c0b746e5SOllivier Robert * the generation of a file is changed according to file generation type 38c0b746e5SOllivier Robert */ 39c0b746e5SOllivier Robert 40c0b746e5SOllivier Robert 41c0b746e5SOllivier Robert /* 42c0b746e5SOllivier Robert * redefine this if your system dislikes filename suffixes like 43c0b746e5SOllivier Robert * X.19910101 or X.1992W50 or .... 44c0b746e5SOllivier Robert */ 45c0b746e5SOllivier Robert #define SUFFIX_SEP '.' 46c0b746e5SOllivier Robert 47c0b746e5SOllivier Robert /* 48c0b746e5SOllivier Robert * other constants 49c0b746e5SOllivier Robert */ 50c0b746e5SOllivier Robert #define FGEN_AGE_SECS (24*60*60) /* life time of FILEGEN_AGE in seconds */ 51c0b746e5SOllivier Robert 52c0b746e5SOllivier Robert static void filegen_open P((FILEGEN *, u_long)); 53c0b746e5SOllivier Robert static int valid_fileref P((char *, char *)); 54c0b746e5SOllivier Robert #ifdef UNUSED 55c0b746e5SOllivier Robert static FILEGEN *filegen_unregister P((char *)); 56c0b746e5SOllivier Robert #endif /* UNUSED */ 57c0b746e5SOllivier Robert 58c0b746e5SOllivier Robert /* 59c0b746e5SOllivier Robert * open a file generation according to the current settings of gen 60c0b746e5SOllivier Robert * will also provide a link to basename if requested to do so 61c0b746e5SOllivier Robert */ 62c0b746e5SOllivier Robert 63c0b746e5SOllivier Robert static void 64c0b746e5SOllivier Robert filegen_open( 65c0b746e5SOllivier Robert FILEGEN *gen, 66c0b746e5SOllivier Robert u_long newid 67c0b746e5SOllivier Robert ) 68c0b746e5SOllivier Robert { 69c0b746e5SOllivier Robert char *filename; 70c0b746e5SOllivier Robert char *basename; 71c0b746e5SOllivier Robert u_int len; 72c0b746e5SOllivier Robert FILE *fp; 73c0b746e5SOllivier Robert struct calendar cal; 74c0b746e5SOllivier Robert 75c0b746e5SOllivier Robert len = strlen(gen->prefix) + strlen(gen->basename) + 1; 76c0b746e5SOllivier Robert basename = (char*)emalloc(len); 77c0b746e5SOllivier Robert sprintf(basename, "%s%s", gen->prefix, gen->basename); 78c0b746e5SOllivier Robert 79c0b746e5SOllivier Robert switch(gen->type) { 80c0b746e5SOllivier Robert default: 81c0b746e5SOllivier Robert msyslog(LOG_ERR, "unsupported file generations type %d for \"%s\" - reverting to FILEGEN_NONE", 82c0b746e5SOllivier Robert gen->type, basename); 83c0b746e5SOllivier Robert gen->type = FILEGEN_NONE; 84c0b746e5SOllivier Robert 85c0b746e5SOllivier Robert /*FALLTHROUGH*/ 86c0b746e5SOllivier Robert case FILEGEN_NONE: 87c0b746e5SOllivier Robert filename = (char*)emalloc(len); 88c0b746e5SOllivier Robert sprintf(filename,"%s", basename); 89c0b746e5SOllivier Robert break; 90c0b746e5SOllivier Robert 91c0b746e5SOllivier Robert case FILEGEN_PID: 92c0b746e5SOllivier Robert filename = (char*)emalloc(len + 1 + 1 + 10); 93c0b746e5SOllivier Robert sprintf(filename,"%s%c#%ld", basename, SUFFIX_SEP, newid); 94c0b746e5SOllivier Robert break; 95c0b746e5SOllivier Robert 96c0b746e5SOllivier Robert case FILEGEN_DAY: 97c0b746e5SOllivier Robert /* You can argue here in favor of using MJD, but 98c0b746e5SOllivier Robert * I would assume it to be easier for humans to interpret dates 99c0b746e5SOllivier Robert * in a format they are used to in everyday life. 100c0b746e5SOllivier Robert */ 101c0b746e5SOllivier Robert caljulian(newid,&cal); 102c0b746e5SOllivier Robert filename = (char*)emalloc(len + 1 + 4 + 2 + 2); 103c0b746e5SOllivier Robert sprintf(filename, "%s%c%04d%02d%02d", 104c0b746e5SOllivier Robert basename, SUFFIX_SEP, cal.year, cal.month, cal.monthday); 105c0b746e5SOllivier Robert break; 106c0b746e5SOllivier Robert 107c0b746e5SOllivier Robert case FILEGEN_WEEK: 108c0b746e5SOllivier Robert /* 109c0b746e5SOllivier Robert * This is still a hack 110c0b746e5SOllivier Robert * - the term week is not correlated to week as it is used 111c0b746e5SOllivier Robert * normally - it just refers to a period of 7 days 112c0b746e5SOllivier Robert * starting at Jan 1 - 'weeks' are counted starting from zero 113c0b746e5SOllivier Robert */ 114c0b746e5SOllivier Robert caljulian(newid,&cal); 115c0b746e5SOllivier Robert filename = (char*)emalloc(len + 1 + 4 + 1 + 2); 116c0b746e5SOllivier Robert sprintf(filename, "%s%c%04dw%02d", 117c0b746e5SOllivier Robert basename, SUFFIX_SEP, cal.year, cal.yearday / 7); 118c0b746e5SOllivier Robert break; 119c0b746e5SOllivier Robert 120c0b746e5SOllivier Robert case FILEGEN_MONTH: 121c0b746e5SOllivier Robert caljulian(newid,&cal); 122c0b746e5SOllivier Robert filename = (char*)emalloc(len + 1 + 4 + 2); 123c0b746e5SOllivier Robert sprintf(filename, "%s%c%04d%02d", 124c0b746e5SOllivier Robert basename, SUFFIX_SEP, cal.year, cal.month); 125c0b746e5SOllivier Robert break; 126c0b746e5SOllivier Robert 127c0b746e5SOllivier Robert case FILEGEN_YEAR: 128c0b746e5SOllivier Robert caljulian(newid,&cal); 129c0b746e5SOllivier Robert filename = (char*)emalloc(len + 1 + 4); 130c0b746e5SOllivier Robert sprintf(filename, "%s%c%04d", basename, SUFFIX_SEP, cal.year); 131c0b746e5SOllivier Robert break; 132c0b746e5SOllivier Robert 133c0b746e5SOllivier Robert case FILEGEN_AGE: 134c0b746e5SOllivier Robert filename = (char*)emalloc(len + 1 + 2 + 10); 135c0b746e5SOllivier Robert sprintf(filename, "%s%ca%08ld", basename, SUFFIX_SEP, newid); 136c0b746e5SOllivier Robert break; 137c0b746e5SOllivier Robert } 138c0b746e5SOllivier Robert 139c0b746e5SOllivier Robert if (gen->type != FILEGEN_NONE) { 140c0b746e5SOllivier Robert /* 141c0b746e5SOllivier Robert * check for existence of a file with name 'basename' 142c0b746e5SOllivier Robert * as we disallow such a file 143c0b746e5SOllivier Robert * if FGEN_FLAG_LINK is set create a link 144c0b746e5SOllivier Robert */ 145c0b746e5SOllivier Robert struct stat stats; 146c0b746e5SOllivier Robert /* 147c0b746e5SOllivier Robert * try to resolve name collisions 148c0b746e5SOllivier Robert */ 149c0b746e5SOllivier Robert static u_long conflicts = 0; 150c0b746e5SOllivier Robert 151c0b746e5SOllivier Robert #ifndef S_ISREG 152c0b746e5SOllivier Robert #define S_ISREG(mode) (((mode) & S_IFREG) == S_IFREG) 153c0b746e5SOllivier Robert #endif 154c0b746e5SOllivier Robert if (stat(basename, &stats) == 0) { 155c0b746e5SOllivier Robert /* Hm, file exists... */ 156c0b746e5SOllivier Robert if (S_ISREG(stats.st_mode)) { 157c0b746e5SOllivier Robert if (stats.st_nlink <= 1) { 158c0b746e5SOllivier Robert /* 159c0b746e5SOllivier Robert * Oh, it is not linked - try to save it 160c0b746e5SOllivier Robert */ 161c0b746e5SOllivier Robert char *savename = (char*)emalloc(len + 1 + 1 + 10 + 10); 162c0b746e5SOllivier Robert sprintf(savename, "%s%c%dC%lu", 163c0b746e5SOllivier Robert basename, 164c0b746e5SOllivier Robert SUFFIX_SEP, 165c0b746e5SOllivier Robert (int) getpid(), 166c0b746e5SOllivier Robert (u_long)conflicts++); 167c0b746e5SOllivier Robert if (rename(basename, savename) != 0) 168c0b746e5SOllivier Robert msyslog(LOG_ERR," couldn't save %s: %m", basename); 169c0b746e5SOllivier Robert free(savename); 170c0b746e5SOllivier Robert } else { 171c0b746e5SOllivier Robert /* 172c0b746e5SOllivier Robert * there is at least a second link tpo this file 173c0b746e5SOllivier Robert * just remove the conflicting one 174c0b746e5SOllivier Robert */ 175c0b746e5SOllivier Robert if ( 176c0b746e5SOllivier Robert #if !defined(VMS) 177c0b746e5SOllivier Robert unlink(basename) != 0 178c0b746e5SOllivier Robert #else 179c0b746e5SOllivier Robert delete(basename) != 0 180c0b746e5SOllivier Robert #endif 181c0b746e5SOllivier Robert ) 182c0b746e5SOllivier Robert msyslog(LOG_ERR, "couldn't unlink %s: %m", basename); 183c0b746e5SOllivier Robert } 184c0b746e5SOllivier Robert } else { 185c0b746e5SOllivier Robert /* 186c0b746e5SOllivier Robert * Ehh? Not a regular file ?? strange !!!! 187c0b746e5SOllivier Robert */ 188c0b746e5SOllivier Robert msyslog(LOG_ERR, "expected regular file for %s (found mode 0%lo)", 189c0b746e5SOllivier Robert basename, (unsigned long)stats.st_mode); 190c0b746e5SOllivier Robert } 191c0b746e5SOllivier Robert } else { 192c0b746e5SOllivier Robert /* 193c0b746e5SOllivier Robert * stat(..) failed, but it is absolutely correct for 194c0b746e5SOllivier Robert * 'basename' not to exist 195c0b746e5SOllivier Robert */ 196c0b746e5SOllivier Robert if (errno != ENOENT) 197c0b746e5SOllivier Robert msyslog(LOG_ERR,"stat(%s) failed: %m", basename); 198c0b746e5SOllivier Robert } 199c0b746e5SOllivier Robert } 200c0b746e5SOllivier Robert 201c0b746e5SOllivier Robert /* 202c0b746e5SOllivier Robert * now, try to open new file generation... 203c0b746e5SOllivier Robert */ 204c0b746e5SOllivier Robert fp = fopen(filename, "a"); 205c0b746e5SOllivier Robert 206c0b746e5SOllivier Robert #ifdef DEBUG 207c0b746e5SOllivier Robert if (debug > 3) 208c0b746e5SOllivier Robert printf("opening filegen (type=%d/id=%lu) \"%s\"\n", 209c0b746e5SOllivier Robert gen->type, (u_long)newid, filename); 210c0b746e5SOllivier Robert #endif 211c0b746e5SOllivier Robert 212c0b746e5SOllivier Robert if (fp == NULL) { 213c0b746e5SOllivier Robert /* open failed -- keep previous state 214c0b746e5SOllivier Robert * 215c0b746e5SOllivier Robert * If the file was open before keep the previous generation. 216c0b746e5SOllivier Robert * This will cause output to end up in the 'wrong' file, 2179c2daa00SOllivier Robert * but I think this is still better than losing output 218c0b746e5SOllivier Robert * 219c0b746e5SOllivier Robert * ignore errors due to missing directories 220c0b746e5SOllivier Robert */ 221c0b746e5SOllivier Robert 222c0b746e5SOllivier Robert if (errno != ENOENT) 223c0b746e5SOllivier Robert msyslog(LOG_ERR, "can't open %s: %m", filename); 224c0b746e5SOllivier Robert } else { 225c0b746e5SOllivier Robert if (gen->fp != NULL) { 226c0b746e5SOllivier Robert fclose(gen->fp); 227c0b746e5SOllivier Robert } 228c0b746e5SOllivier Robert gen->fp = fp; 229c0b746e5SOllivier Robert gen->id = newid; 230c0b746e5SOllivier Robert 231c0b746e5SOllivier Robert if (gen->flag & FGEN_FLAG_LINK) { 232c0b746e5SOllivier Robert /* 233c0b746e5SOllivier Robert * need to link file to basename 234c0b746e5SOllivier Robert * have to use hardlink for now as I want to allow 235c0b746e5SOllivier Robert * gen->basename spanning directory levels 236c0b746e5SOllivier Robert * this would make it more complex to get the correct 237c0b746e5SOllivier Robert * filename for symlink 238c0b746e5SOllivier Robert * 239c0b746e5SOllivier Robert * Ok, it would just mean taking the part following 240c0b746e5SOllivier Robert * the last '/' in the name.... Should add it later.... 241c0b746e5SOllivier Robert */ 242c0b746e5SOllivier Robert 243c0b746e5SOllivier Robert /* Windows NT does not support file links -Greg Schueman 1/18/97 */ 244c0b746e5SOllivier Robert 245c0b746e5SOllivier Robert #if defined SYS_WINNT || defined SYS_VXWORKS 246c0b746e5SOllivier Robert SetLastError(0); /* On WinNT, don't support FGEN_FLAG_LINK */ 247c0b746e5SOllivier Robert #elif defined(VMS) 248c0b746e5SOllivier Robert errno = 0; /* On VMS, don't support FGEN_FLAG_LINK */ 249c0b746e5SOllivier Robert #else /* not (VMS) / VXWORKS / WINNT ; DO THE LINK) */ 250c0b746e5SOllivier Robert if (link(filename, basename) != 0) 251c0b746e5SOllivier Robert if (errno != EEXIST) 252c0b746e5SOllivier Robert msyslog(LOG_ERR, "can't link(%s, %s): %m", filename, basename); 253c0b746e5SOllivier Robert #endif /* SYS_WINNT || VXWORKS */ 254c0b746e5SOllivier Robert } /* flags & FGEN_FLAG_LINK */ 255c0b746e5SOllivier Robert } /* else fp == NULL */ 256c0b746e5SOllivier Robert 257c0b746e5SOllivier Robert free(basename); 258c0b746e5SOllivier Robert free(filename); 259c0b746e5SOllivier Robert return; 260c0b746e5SOllivier Robert } 261c0b746e5SOllivier Robert 262c0b746e5SOllivier Robert /* 263c0b746e5SOllivier Robert * this function sets up gen->fp to point to the correct 264c0b746e5SOllivier Robert * generation of the file for the time specified by 'now' 265c0b746e5SOllivier Robert * 266c0b746e5SOllivier Robert * 'now' usually is interpreted as second part of a l_fp as is in the cal... 267c0b746e5SOllivier Robert * library routines 268c0b746e5SOllivier Robert */ 269c0b746e5SOllivier Robert 270c0b746e5SOllivier Robert void 271c0b746e5SOllivier Robert filegen_setup( 272c0b746e5SOllivier Robert FILEGEN *gen, 273c0b746e5SOllivier Robert u_long now 274c0b746e5SOllivier Robert ) 275c0b746e5SOllivier Robert { 276c0b746e5SOllivier Robert u_long new_gen = ~ (u_long) 0; 277c0b746e5SOllivier Robert struct calendar cal; 278c0b746e5SOllivier Robert 279c0b746e5SOllivier Robert if (!(gen->flag & FGEN_FLAG_ENABLED)) { 280c0b746e5SOllivier Robert if (gen->fp != NULL) 281c0b746e5SOllivier Robert fclose(gen->fp); 282c0b746e5SOllivier Robert return; 283c0b746e5SOllivier Robert } 284c0b746e5SOllivier Robert 285c0b746e5SOllivier Robert switch (gen->type) { 286c0b746e5SOllivier Robert case FILEGEN_NONE: 287c0b746e5SOllivier Robert if (gen->fp != NULL) return; /* file already open */ 288c0b746e5SOllivier Robert break; 289c0b746e5SOllivier Robert 290c0b746e5SOllivier Robert case FILEGEN_PID: 291c0b746e5SOllivier Robert new_gen = getpid(); 292c0b746e5SOllivier Robert break; 293c0b746e5SOllivier Robert 294c0b746e5SOllivier Robert case FILEGEN_DAY: 295c0b746e5SOllivier Robert caljulian(now, &cal); 296c0b746e5SOllivier Robert cal.hour = cal.minute = cal.second = 0; 297c0b746e5SOllivier Robert new_gen = caltontp(&cal); 298c0b746e5SOllivier Robert break; 299c0b746e5SOllivier Robert 300c0b746e5SOllivier Robert case FILEGEN_WEEK: 301c0b746e5SOllivier Robert /* Would be nice to have a calweekstart() routine */ 302c0b746e5SOllivier Robert /* so just use a hack ... */ 303c0b746e5SOllivier Robert /* just round time to integral 7 day period for actual year */ 304c0b746e5SOllivier Robert new_gen = now - (now - calyearstart(now)) % TIMES7(SECSPERDAY) 305c0b746e5SOllivier Robert + 60; 306c0b746e5SOllivier Robert /* 307c0b746e5SOllivier Robert * just to be sure - 308c0b746e5SOllivier Robert * the computation above would fail in the presence of leap seconds 309c0b746e5SOllivier Robert * so at least carry the date to the next day (+60 (seconds)) 310c0b746e5SOllivier Robert * and go back to the start of the day via calendar computations 311c0b746e5SOllivier Robert */ 312c0b746e5SOllivier Robert caljulian(new_gen, &cal); 313c0b746e5SOllivier Robert cal.hour = cal.minute = cal.second = 0; 314c0b746e5SOllivier Robert new_gen = caltontp(&cal); 315c0b746e5SOllivier Robert break; 316c0b746e5SOllivier Robert 317c0b746e5SOllivier Robert case FILEGEN_MONTH: 318c0b746e5SOllivier Robert caljulian(now, &cal); 3199c2daa00SOllivier Robert cal.yearday = (u_short) (cal.yearday - cal.monthday + 1); 320c0b746e5SOllivier Robert cal.monthday = 1; 321c0b746e5SOllivier Robert cal.hour = cal.minute = cal.second = 0; 322c0b746e5SOllivier Robert new_gen = caltontp(&cal); 323c0b746e5SOllivier Robert break; 324c0b746e5SOllivier Robert 325c0b746e5SOllivier Robert case FILEGEN_YEAR: 326c0b746e5SOllivier Robert new_gen = calyearstart(now); 327c0b746e5SOllivier Robert break; 328c0b746e5SOllivier Robert 329c0b746e5SOllivier Robert case FILEGEN_AGE: 330c0b746e5SOllivier Robert new_gen = current_time - (current_time % FGEN_AGE_SECS); 331c0b746e5SOllivier Robert break; 332c0b746e5SOllivier Robert } 333c0b746e5SOllivier Robert /* 334c0b746e5SOllivier Robert * try to open file if not yet open 335c0b746e5SOllivier Robert * reopen new file generation file on change of generation id 336c0b746e5SOllivier Robert */ 337c0b746e5SOllivier Robert if (gen->fp == NULL || gen->id != new_gen) { 338c0b746e5SOllivier Robert filegen_open(gen, new_gen); 339c0b746e5SOllivier Robert } 340c0b746e5SOllivier Robert } 341c0b746e5SOllivier Robert 342c0b746e5SOllivier Robert 343c0b746e5SOllivier Robert /* 344c0b746e5SOllivier Robert * change settings for filegen files 345c0b746e5SOllivier Robert */ 346c0b746e5SOllivier Robert void 347c0b746e5SOllivier Robert filegen_config( 348c0b746e5SOllivier Robert FILEGEN *gen, 349c0b746e5SOllivier Robert char *basename, 350c0b746e5SOllivier Robert u_int type, 351c0b746e5SOllivier Robert u_int flag 352c0b746e5SOllivier Robert ) 353c0b746e5SOllivier Robert { 354c0b746e5SOllivier Robert /* 355c0b746e5SOllivier Robert * if nothing would be changed... 356c0b746e5SOllivier Robert */ 357c0b746e5SOllivier Robert if ((basename == gen->basename || strcmp(basename,gen->basename) == 0) && 358c0b746e5SOllivier Robert type == gen->type && 359c0b746e5SOllivier Robert flag == gen->flag) 360c0b746e5SOllivier Robert return; 361c0b746e5SOllivier Robert 362c0b746e5SOllivier Robert /* 363c0b746e5SOllivier Robert * validate parameters 364c0b746e5SOllivier Robert */ 365c0b746e5SOllivier Robert if (!valid_fileref(gen->prefix,basename)) 366c0b746e5SOllivier Robert return; 367c0b746e5SOllivier Robert 368c0b746e5SOllivier Robert if (gen->fp != NULL) 369c0b746e5SOllivier Robert fclose(gen->fp); 370c0b746e5SOllivier Robert 371c0b746e5SOllivier Robert #ifdef DEBUG 372c0b746e5SOllivier Robert if (debug > 2) 373c0b746e5SOllivier Robert printf("configuring filegen:\n\tprefix:\t%s\n\tbasename:\t%s -> %s\n\ttype:\t%d -> %d\n\tflag: %x -> %x\n", 374c0b746e5SOllivier Robert gen->prefix, gen->basename, basename, gen->type, type, gen->flag, flag); 375c0b746e5SOllivier Robert #endif 376c0b746e5SOllivier Robert if (gen->basename != basename || strcmp(gen->basename, basename) != 0) { 377c0b746e5SOllivier Robert free(gen->basename); 378c0b746e5SOllivier Robert gen->basename = (char*)emalloc(strlen(basename) + 1); 379c0b746e5SOllivier Robert strcpy(gen->basename, basename); 380c0b746e5SOllivier Robert } 3819c2daa00SOllivier Robert gen->type = (u_char) type; 3829c2daa00SOllivier Robert gen->flag = (u_char) flag; 383c0b746e5SOllivier Robert 384c0b746e5SOllivier Robert /* 385c0b746e5SOllivier Robert * make filegen use the new settings 386c0b746e5SOllivier Robert * special action is only required when a generation file 387c0b746e5SOllivier Robert * is currently open 388c0b746e5SOllivier Robert * otherwise the new settings will be used anyway at the next open 389c0b746e5SOllivier Robert */ 390c0b746e5SOllivier Robert if (gen->fp != NULL) { 391c0b746e5SOllivier Robert l_fp now; 392c0b746e5SOllivier Robert 393c0b746e5SOllivier Robert get_systime(&now); 394c0b746e5SOllivier Robert filegen_setup(gen, now.l_ui); 395c0b746e5SOllivier Robert } 396c0b746e5SOllivier Robert } 397c0b746e5SOllivier Robert 398c0b746e5SOllivier Robert 399c0b746e5SOllivier Robert /* 400c0b746e5SOllivier Robert * check whether concatenating prefix and basename 401c0b746e5SOllivier Robert * yields a legal filename 402c0b746e5SOllivier Robert */ 403c0b746e5SOllivier Robert static int 404c0b746e5SOllivier Robert valid_fileref( 405c0b746e5SOllivier Robert char *prefix, 406c0b746e5SOllivier Robert char *basename 407c0b746e5SOllivier Robert ) 408c0b746e5SOllivier Robert { 409c0b746e5SOllivier Robert /* 410c0b746e5SOllivier Robert * prefix cannot be changed dynamically 411c0b746e5SOllivier Robert * (within the context of filegen) 412c0b746e5SOllivier Robert * so just reject basenames containing '..' 413c0b746e5SOllivier Robert * 414c0b746e5SOllivier Robert * ASSUMPTION: 415c0b746e5SOllivier Robert * file system parts 'below' prefix may be 416c0b746e5SOllivier Robert * specified without infringement of security 417c0b746e5SOllivier Robert * 418c0b746e5SOllivier Robert * restricing prefix to legal values 419c0b746e5SOllivier Robert * has to be ensured by other means 420c0b746e5SOllivier Robert * (however, it would be possible to perform some checks here...) 421c0b746e5SOllivier Robert */ 422c0b746e5SOllivier Robert register char *p = basename; 423c0b746e5SOllivier Robert 424c0b746e5SOllivier Robert /* 425c0b746e5SOllivier Robert * Just to catch, dumb errors opening up the world... 426c0b746e5SOllivier Robert */ 427c0b746e5SOllivier Robert if (prefix == NULL || *prefix == '\0') 428c0b746e5SOllivier Robert return 0; 429c0b746e5SOllivier Robert 430c0b746e5SOllivier Robert if (basename == NULL) 431c0b746e5SOllivier Robert return 0; 432c0b746e5SOllivier Robert 433c0b746e5SOllivier Robert for (p = basename; p; p = strchr(p, '/')) { 434c0b746e5SOllivier Robert if (*p == '.' && *(p+1) == '.' && (*(p+2) == '\0' || *(p+2) == '/')) 435c0b746e5SOllivier Robert return 0; 436c0b746e5SOllivier Robert } 437c0b746e5SOllivier Robert 438c0b746e5SOllivier Robert return 1; 439c0b746e5SOllivier Robert } 440c0b746e5SOllivier Robert 441c0b746e5SOllivier Robert 442c0b746e5SOllivier Robert /* 443c0b746e5SOllivier Robert * filegen registry 444c0b746e5SOllivier Robert */ 445c0b746e5SOllivier Robert 446c0b746e5SOllivier Robert static struct filegen_entry { 447c0b746e5SOllivier Robert char *name; 448c0b746e5SOllivier Robert FILEGEN *filegen; 449c0b746e5SOllivier Robert struct filegen_entry *next; 450c0b746e5SOllivier Robert } *filegen_registry = NULL; 451c0b746e5SOllivier Robert 452c0b746e5SOllivier Robert 453c0b746e5SOllivier Robert FILEGEN * 454c0b746e5SOllivier Robert filegen_get( 455c0b746e5SOllivier Robert char *name 456c0b746e5SOllivier Robert ) 457c0b746e5SOllivier Robert { 458c0b746e5SOllivier Robert struct filegen_entry *f = filegen_registry; 459c0b746e5SOllivier Robert 460c0b746e5SOllivier Robert while(f) { 461c0b746e5SOllivier Robert if (f->name == name || strcmp(name, f->name) == 0) { 462c0b746e5SOllivier Robert #ifdef XXX /* this gives the Alpha compiler fits */ 463c0b746e5SOllivier Robert if (debug > 3) 464c0b746e5SOllivier Robert printf("filegen_get(\"%s\") = %x\n", name, 465c0b746e5SOllivier Robert (u_int)f->filegen); 466c0b746e5SOllivier Robert #endif 467c0b746e5SOllivier Robert return f->filegen; 468c0b746e5SOllivier Robert } 469c0b746e5SOllivier Robert f = f->next; 470c0b746e5SOllivier Robert } 471c0b746e5SOllivier Robert #ifdef DEBUG 472c0b746e5SOllivier Robert if (debug > 3) 473c0b746e5SOllivier Robert printf("filegen_get(\"%s\") = NULL\n", name); 474c0b746e5SOllivier Robert #endif 475c0b746e5SOllivier Robert return NULL; 476c0b746e5SOllivier Robert } 477c0b746e5SOllivier Robert 478c0b746e5SOllivier Robert void 479c0b746e5SOllivier Robert filegen_register( 480c0b746e5SOllivier Robert const char *name, 481c0b746e5SOllivier Robert FILEGEN *filegen 482c0b746e5SOllivier Robert ) 483c0b746e5SOllivier Robert { 484c0b746e5SOllivier Robert struct filegen_entry **f = &filegen_registry; 485c0b746e5SOllivier Robert 486c0b746e5SOllivier Robert #ifdef XXX /* this gives the Alpha compiler fits */ 487c0b746e5SOllivier Robert if (debug > 3) 488c0b746e5SOllivier Robert printf("filegen_register(\"%s\",%x)\n", name, (u_int)filegen); 489c0b746e5SOllivier Robert #endif 490c0b746e5SOllivier Robert while (*f) { 491c0b746e5SOllivier Robert if ((*f)->name == name || strcmp(name, (*f)->name) == 0) { 492c0b746e5SOllivier Robert #ifdef XXX /* this gives the Alpha compiler fits */ 493c0b746e5SOllivier Robert if (debug > 4) { 494c0b746e5SOllivier Robert printf("replacing filegen %x\n", (u_int)(*f)->filegen); 495c0b746e5SOllivier Robert } 496c0b746e5SOllivier Robert #endif 497c0b746e5SOllivier Robert (*f)->filegen = filegen; 498c0b746e5SOllivier Robert return; 499c0b746e5SOllivier Robert } 500c0b746e5SOllivier Robert f = &((*f)->next); 501c0b746e5SOllivier Robert } 502c0b746e5SOllivier Robert 503c0b746e5SOllivier Robert *f = (struct filegen_entry *) emalloc(sizeof(struct filegen_entry)); 504c0b746e5SOllivier Robert if (*f) { 505c0b746e5SOllivier Robert (*f)->next = NULL; 506c0b746e5SOllivier Robert (*f)->name = (char*)emalloc(strlen(name) + 1); 507c0b746e5SOllivier Robert strcpy((*f)->name, name); 508c0b746e5SOllivier Robert (*f)->filegen = filegen; 509c0b746e5SOllivier Robert #ifdef DEBUG 510c0b746e5SOllivier Robert if (debug > 5) { 511c0b746e5SOllivier Robert printf("adding new filegen\n"); 512c0b746e5SOllivier Robert } 513c0b746e5SOllivier Robert #endif 514c0b746e5SOllivier Robert } 515c0b746e5SOllivier Robert 516c0b746e5SOllivier Robert return; 517c0b746e5SOllivier Robert } 518c0b746e5SOllivier Robert 519c0b746e5SOllivier Robert #ifdef UNUSED 520c0b746e5SOllivier Robert static FILEGEN * 521c0b746e5SOllivier Robert filegen_unregister( 522c0b746e5SOllivier Robert char *name 523c0b746e5SOllivier Robert ) 524c0b746e5SOllivier Robert { 525c0b746e5SOllivier Robert struct filegen_entry **f = &filegen_registry; 526c0b746e5SOllivier Robert 527c0b746e5SOllivier Robert #ifdef DEBUG 528c0b746e5SOllivier Robert if (debug > 3) 529c0b746e5SOllivier Robert printf("filegen_unregister(\"%s\")\n", name); 530c0b746e5SOllivier Robert #endif 531c0b746e5SOllivier Robert 532c0b746e5SOllivier Robert while (*f) { 533c0b746e5SOllivier Robert if (strcmp((*f)->name,name) == 0) { 534c0b746e5SOllivier Robert struct filegen_entry *ff = *f; 535c0b746e5SOllivier Robert FILEGEN *fg; 536c0b746e5SOllivier Robert 537c0b746e5SOllivier Robert *f = (*f)->next; 538c0b746e5SOllivier Robert fg = ff->filegen; 539c0b746e5SOllivier Robert free(ff->name); 540c0b746e5SOllivier Robert free(ff); 541c0b746e5SOllivier Robert return fg; 542c0b746e5SOllivier Robert } 543c0b746e5SOllivier Robert f = &((*f)->next); 544c0b746e5SOllivier Robert } 545c0b746e5SOllivier Robert return NULL; 546c0b746e5SOllivier Robert } 547c0b746e5SOllivier Robert #endif /* UNUSED */ 548