Patch: Elm ME+ 2.5 PLalpha63 -> Elm ME+ 2.5 PLalpha64 [2/4] (4/5)
From
Kari Hurtta@21:1/5 to
All on Tue Jul 2 20:52:17 2024
[continued from previous message]
+ last_read_def_rewrite = ison(H->lread_open_flags,
+ LREAD_OPEN_SUGGEST_REWRITE);
+ }
+
+
+ if (write_last_read_cache(H,
+ dir_last_read,
+ locking,
+ NULL /* errno_res */,
+
+ /* commentfile,actor,version_buff */ + NULL,NULL,NULL
+ )) {
+
+ DPRINT(Debug,14,(&Debug,
+ "write_last_read_cache: %s: %s updated\n",
+ dir_last_read->sys_dir ?
+ dir_last_read->sys_dir : "fallback file", + dir_last_read->cache_file_name));
+
+ if (last_read_def_cache == dir_last_read) {
+ last_read_def_rewrite = 0;
+ }
+
+ }
+
+ free_last_read_open(&H);
+ }
+ }
+ }
+
+ }
+
+ enum last_read_default { last_read_def_existing = 0,
+ last_read_def_create };
+
+ static struct last_read_cache * give_last_read P_((const char * sys_dir,
+ enum last_read_location last_read_loc,
+ const char * res_dir,
+ enum last_read_default default_create
+ ));
+
+ static struct last_read_cache * give_last_read(sys_dir,last_read_loc,res_dir,
+ default_create)
+ const char * sys_dir;
+ enum last_read_location last_read_loc;
+ const char * res_dir;
+ enum last_read_default default_create;
+ {
+ struct last_read_cache * ret = NULL;
+ char * fname = NULL;
+
+ DPRINT(Debug,13,(&Debug,"give_last_read: sys_dir=%s last_read_loc=%d",sys_dir,last_read_loc));
+ switch (last_read_loc) {
+ case read_loc_none: DPRINT(Debug,13,(&Debug," read_loc_none")); break;
+ case read_loc_dir: DPRINT(Debug,13,(&Debug," read_loc_dir")); break;
+ case read_loc_def: DPRINT(Debug,13,(&Debug," read_loc_def")); break;
+ }
+ if (res_dir) {
+ DPRINT(Debug,13,(&Debug," res_dir=%s",res_dir));
+ }
+ DPRINT(Debug,13,(&Debug," default_create=%d",default_create));
+ switch (default_create) {
+ case last_read_def_existing: DPRINT(Debug,13,(&Debug," last_read_def_existing")); break;
+ case last_read_def_create: DPRINT(Debug,13,(&Debug," last_read_def_create")); break;
+ }
+ DPRINT(Debug,13,(&Debug,"\n"));
+
+ fname = give_cache_file_name(sys_dir,last_read_loc);
+
+ if (fname) {
+ enum sort_list_search_op op = sort_list_search_normal;
+ enum use_lastread_v use_lastread =
+ give_dt_enumerate_as_int(&use_last_read_file);
+
+
+ switch (use_lastread) {
+ case use_lastread_no:
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s - use-last-read disabled\n",
+ sys_dir));
+ goto fail;
+
+ case use_lastread_yes:
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s - use-last-read enabled\n",
+ sys_dir));
+ op = sort_list_search_create;
+ break;
+ case use_lastread_auto:
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s - use-last-read auto\n",
+ sys_dir));
+
+ if (0) {
+ case use_lastread_existing:
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s - use-last-read existing\n",
+ sys_dir));
+ }
+
+ switch (default_create) {
+ case last_read_def_create:
+ op = sort_list_search_create;
+ break;
+ case last_read_def_existing: {
+ enum syscall_status r_access =
+ access(fname, ACCESS_EXISTS);
+
+ switch ( r_access) {
+ int err UNUSED_VAROK;
+ case syscall_success:
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s - %s exists\n",
+ sys_dir,fname));
+ op = sort_list_search_create;
+ break;
+ case syscall_error:
+ err = errno;
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s - %s gives: %s\n",
+ sys_dir,fname,
+ strerror(err)));
+ break;
+ }
+ }
+ break;
+ }
+
+ break;
+ case NUM_use_lastread:
+ break;
+ }
+
+ switch (last_read_loc) {
+
+ case read_loc_none:
+ break;
+ case read_loc_dir:
+
+ if (res_dir) {
+ struct last_read_cache_def def = NULL_last_read_cache_def;
+ union sort_item_default def0;
+ union sort_item res;
+ size_t idx;
+ union sort_key key;
+
+ if (! last_read_dir_cache) {
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s -- setting last_read_dir_cache\n",
+ sys_dir));
+
+ last_read_dir_cache = alloc_sort_list(& last_read_cache_op,2);
+ }
+
+ def.st = NULL;
+ def.prealloc = 5;
+ def.fchanges = NULL;
+
+ def0.last_read_cache = &def;
+ def.cache_file_name = fname;
+
+ res.last_read_cache = NULL;
+ key.str = res_dir;
+ idx = 0;
+
+ /* Increments refcount */;
+ if (search_sort_list_item(last_read_dir_cache,
+ op,
+ key,def0,&res,&idx,NULL)) {
+
+ if (res.last_read_cache) {
+ if (LAST_READ_CACHE_magic != res.last_read_cache->magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"give_last_read",
+ "Bad magic type (last_read_cache)",0);
+
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s -- last read %Q: idx #%zu found\n",
+ sys_dir,res_dir,idx));
+
+ ret = res.last_read_cache;
+
+ if (! ret->read) {
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s -- need initial read\n",
+ sys_dir));
+
+ reload_last_read_cache(ret,NULL,NULL,
+ cache_guess_locking(ret),
+ last_read_check,
+ NULL /* errno_res */);
+ } else {
+ int err = 0;
+ enum file_changes_result change_status
+ = test_file_changes(fname,
+ & ret->cache_file,
+ & err);
+
+ switch (change_status) {
+ case no_file_changes:
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s last_read %s not changed\n",
+ sys_dir,fname));
+ break;
+ case file_changes_error:
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s last_read %s not available %s\n",
+ sys_dir,fname,strerror(err))); + break;
+ case have_file_changes:
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s last_read %s need reload\n",
+ sys_dir,fname));
+
+ reload_last_read_cache(ret,NULL,NULL,
+ cache_guess_locking(ret),
+ last_read_check,
+ NULL /* errno res */);
+ break;
+ }
+ }
+
+ } else {
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s -- last read for %Q: search_sort_list_item did not set last_read_cache, idx #%zu\n",
+ sys_dir,res_dir,idx));
+ }
+
+ } else {
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s -- last read for %Q not found or created\n",
+ sys_dir,res_dir));
+ }
+ } else {
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s -- target dir not set\n", + sys_dir));
+ }
+ break;
+ case read_loc_def: {
+ struct last_read_open * H = NULL;
+
+ if (last_read_def_cache) {
+
+ ret = last_read_def_cache;
+ inc_last_read_cache_refcount(ret);
+
+ if (! ret->read) {
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s -- need initial read for default cache %s\n",
+ sys_dir,fname));
+
+ reload_last_read_cache(ret,&H,NULL,
+ &conf_merge_locking,
+ last_read_check,
+ NULL /* errno_res */);
+ } else {
+
+ int err = 0;
+ enum file_changes_result change_status
+ = test_file_changes(fname,
+ & ret->cache_file,
+ & err);
+
+ switch (change_status) {
+ case no_file_changes:
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s last_read %s not changed\n",
+ sys_dir,fname));
+ break;
+ case file_changes_error:
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s last_read %s not available %s\n",
+ sys_dir,fname,strerror(err)));
+ break;
+ case have_file_changes:
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s last_read %s need reload\n",
+ sys_dir,fname));
+
+ reload_last_read_cache(ret,&H,NULL,
+ &conf_merge_locking,
+ last_read_check,
+ NULL /* errno_res */);
+ break;
+ }
+ }
+
+ } else {
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s -- default cache %s not read\n",
+ sys_dir,fname));
+
+ last_read_def_cache =
+ load_last_read_cache(user_last_read_def,NULL,
+ &H,NULL, &conf_merge_locking,
+ last_read_check);
+
+ if (last_read_def_cache) {
+ ret = last_read_def_cache;
+ inc_last_read_cache_refcount(ret);
+
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s -- succeed to read default cache %s\n",
+ sys_dir,fname));
+ } else {
+ switch (default_create) {
+ case last_read_def_create:
+ last_read_def_cache = malloc_last_read_cache(NULL /* sys_dir */,
+ NULL /* struct stat */,
+ 1,
+ &last_read_def_fchanges,
+ fname);
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s - created dummy default cache %s\n",
+ sys_dir,fname));
+
+ ret = last_read_def_cache;
+ inc_last_read_cache_refcount(ret);
+
+ break;
+ case last_read_def_existing:
+ break;
+ }
+ }
+ }
+
+ if (H) {
+
+ if (LAST_READ_OPEN_magic != H->magic)
+ panic("MBX PANIC",__FILE__,__LINE__,
+ "write_last_read_cache",
+ "Bad magic number (last_read_open)",0);
+
+ if (last_read_def_cache) {
+ last_read_def_rewrite = ison(H->lread_open_flags,
+ LREAD_OPEN_SUGGEST_REWRITE);
+ }
+
+ free_last_read_open(&H);
+ }
+
+ }
+ break;
+ }
+
+ fail:
+ free(fname);
+ fname = NULL;
+ } else {
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read: %s -- cache file name not set\n",
+ sys_dir));
+ }
+
+ if (ret) {
+ if (LAST_READ_CACHE_magic != ret->magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"give_last_read",
+ "Bad magic type (last_read_cache)",0);
+
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read=%p",ret));
+ if (ret->sys_dir) {
+ DPRINT(Debug,13,(&Debug," sys_dir=%s",ret->sys_dir));
+ }
+ if (ret->cache_file_name) {
+ DPRINT(Debug,13,(&Debug," cache_file_name=%s",ret->cache_file_name));
+ }
+ } else {
+ DPRINT(Debug,13,(&Debug,
+ "give_last_read=NULL"));
+ }
+
+ DPRINT(Debug,13,(&Debug,"; requested sys_dir=%s",sys_dir));
+ if (res_dir) {
+ DPRINT(Debug,13,(&Debug," res_dir=%s",res_dir));
+ }
+ DPRINT(Debug,13,(&Debug,"\n"));
+
+ return ret;
+ }
+
+ /* Result is malloced if *free_sys_dir is set */
+ static char * stat_file_to_sys_dir P_((const char * stat_file,
+ int * free_sys_dir_p
+ ));
+ static char * stat_file_to_sys_dir (stat_file,free_sys_dir_p)
+ const char * stat_file;
+ int * free_sys_dir_p;
+ {
+ char * sys_dir = NULL;
+ int free_sys_dir = * free_sys_dir_p;
+
+ const char * p = strrchr(stat_file,'/');
+
+ if (p) {
+ size_t len = (p - stat_file);
+
+ sys_dir = safe_malloc(len+1);
+ free_sys_dir = 1;
+ strnfcpy(sys_dir,stat_file,len,len+1,NULL);
+
+ } else {
+ sys_dir = ".";
+ free_sys_dir = 0;
+ }
+
+
+ DPRINT(Debug,14,(&Debug,
+ "stat_file_to_sys_dir=%s; stat_file=%s\n",
+ sys_dir,
+ stat_file));
+
+ * free_sys_dir_p = free_sys_dir;
+ return sys_dir;
+ }
+
+ /* Increments refcount - may change or open new cache
+ does not reload cache if directory is corrent
+ */
+ struct last_read_cache * upgrade_last_read(dir_last_read,
+ stat_file,
+ stat_buf)
+ struct last_read_cache * dir_last_read;
+ const char * stat_file;
+ struct stat * stat_buf;
+ {
+ struct last_read_cache *ret = NULL;
+ int need_upgrade = 0;
+
+ int free_sys_dir = 0;
+ char * sys_dir = stat_file_to_sys_dir(stat_file,
+ &free_sys_dir);
+ const char * res_dir = NULL;
+
+ enum last_read_location last_read_loc = read_loc_none;
+
+
+ DPRINT(Debug,13,(&Debug,
+ "upgrade_last_read: %s => sys_dir=%Q\n",
+ stat_file,sys_dir));
+
+ last_read_loc = last_read_dir_to_loc(sys_dir,&res_dir);
+
+ DPRINT(Debug,13,(&Debug,
+ "upgrade_last_read: %s => location %d",
+ stat_file,
+ last_read_loc));
+
+ switch (last_read_loc) {
+ case read_loc_none: DPRINT(Debug,13,(&Debug," read_loc_none"));
+ break;
+ case read_loc_dir: DPRINT(Debug,13,(&Debug," read_loc_dir"));
+ break;
+ case read_loc_def: DPRINT(Debug,13,(&Debug," read_loc_def"));
+ break;
+ }
+
+ if (res_dir) {
+ DPRINT(Debug,13,(&Debug," res_dir=%Q",res_dir));
+ }
+ DPRINT(Debug,13,(&Debug,"\n"));
+
+ if (dir_last_read) {
+
+ if (LAST_READ_CACHE_magic != dir_last_read->magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"upgrade_last_read",
+ "Bad magic type (last_read_cache)",0);
+
+ DPRINT(Debug,13,(&Debug,
+ "upgrade_last_read: %s dir_last_read=%p",
+ stat_file,dir_last_read));
+ if (dir_last_read->sys_dir) {
+ DPRINT(Debug,13,(&Debug," sys_dir=%s",dir_last_read->sys_dir));
+ }
+ if (dir_last_read->cache_file_name) {
+ DPRINT(Debug,13,(&Debug," cache_file_name=%s",
+ dir_last_read->cache_file_name));
+ }
+ DPRINT(Debug,13,(&Debug,"\n"));
+
+ switch (last_read_loc) {
+ case read_loc_none: need_upgrade = 1; break;
+ case read_loc_dir:
+ if (res_dir && dir_last_read->sys_dir &&
+ same_dir_str(res_dir,dir_last_read->sys_dir)) {
+
+ if (FILE_CHANGES_magic != dir_last_read->cache_file.magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"upgrade_last_read",
+ "Bad magic type (file_changes)",0);
+
+ if (stat_buf &&
+ dir_last_read->cache_file.dev != stat_buf->st_dev) {
+
+ DPRINT(Debug,13,(&Debug,
+ "upgrade_last_read: %s -- last_read dev %ld does not match %Q dev %ld\n",
+ stat_file,
+ (long)(dir_last_read->cache_file.dev),
+ res_dir,
+ (long)(stat_buf->st_dev)));
+ need_upgrade = 1;
+ }
+
+ } else {
+ need_upgrade = 1;
+ if (res_dir && dir_last_read->sys_dir) {
+ DPRINT(Debug,13,(&Debug,
+ "upgrade_last_read: %s -- last_read %Q does not match to %Q\n",
+ stat_file,dir_last_read->sys_dir,
+ res_dir));
+
+ }
+ }
+ break;
+ case read_loc_def:
+ if (last_read_def_cache != dir_last_read)
+ need_upgrade = 1;
+ break;
+ }
+
+ if (need_upgrade) {
+ DPRINT(Debug,13,(&Debug,
+ "upgrade_last_read: %s -- last read %s need upgrade\n",
+ stat_file,
+ dir_last_read->cache_file_name));
+ }
+ }
+
+
+ if (need_upgrade || !dir_last_read) {
+
+ ret = give_last_read(sys_dir,last_read_loc,res_dir,
+ dir_last_read ? last_read_def_create :
+ last_read_def_existing
+ );
+
+ DPRINT(Debug,13,(&Debug,
+ "upgrade_last_read: %s ",
+ stat_file));
+
+ if (ret) {
+ DPRINT(Debug,13,(&Debug," last_read for %s changed or set",
+ sys_dir));
+ } else {
+ DPRINT(Debug,13,(&Debug," last_read for %s failed",
+ sys_dir));
+ }
+ DPRINT(Debug,13,(&Debug,"\n"));
+
+ } else {
+ if (FILE_CHANGES_magic != dir_last_read->cache_file.magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"upgrade_last_read",
+ "Bad magic type (file_changes)",0);
+
+ ret = dir_last_read;
+ inc_last_read_cache_refcount(ret);
+
+ DPRINT(Debug,13,(&Debug,
+ "upgrade_last_read: %s last_read %s not changed\n",
+ stat_file,dir_last_read->cache_file_name));
+
+ }
+
+ if (sys_dir) {
+ if (free_sys_dir)
+ free(sys_dir);
+ sys_dir = NULL;
+ }
+
+ if (ret) {
+ if (LAST_READ_CACHE_magic != ret->magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"upgrade_last_read",
+ "Bad magic type (last_read_cache)",0);
+
+ DPRINT(Debug,13,(&Debug,
+ "upgrade_last_read=%p",ret));
+ if (ret->sys_dir) {
+ DPRINT(Debug,13,(&Debug," sys_dir=%s",ret->sys_dir));
+ }
+ if (ret->cache_file_name) {
+ DPRINT(Debug,13,(&Debug," cache_file_name=%s",ret->cache_file_name));
+ }
+ } else {
+ DPRINT(Debug,13,(&Debug,
+ "upgrade_last_read=NULL"));
+ }
+ DPRINT(Debug,13,(&Debug,"; stat_file=%s\n",stat_file));
+
+ return ret;
+ }
+
+ void inc_last_read_cache_refcount(cache)
+ struct last_read_cache * cache;
+ {
+ if (LAST_READ_CACHE_magic != cache->magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"inc_last_read_cache_refcount",
+ "Bad magic type (last_read_cache)",0);
+
+ cache->refcount++;
+ }
+
+ /* Decremetns refcount */
+ void free_last_read_cache(cache)
+ struct last_read_cache ** cache;
+ {
+
+ if (LAST_READ_CACHE_magic != (*cache)->magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"free_last_read_cache",
+ "Bad magic type (last_read_cache)",0);
+
+ if ((*cache)->refcount < 1)
+ panic("MBX PANIC",__FILE__,__LINE__,"free_last_read_cache",
+ "Bad refcount",0);
+
+ (*cache)->refcount--;
+
+ if ((*cache)->refcount > 0) {
+ (*cache) = NULL;
+
+ return;
+ }
+
+
+ if ((*cache)->sys_dir) {
+ free((*cache)->sys_dir);
+
+ (*cache)->sys_dir = NULL;
+ }
+
+ if ((*cache)->cached_name)
+ free_string_sort(& ((*cache)->cached_name));
+
+ if ((*cache)->cache_file_name) {
+ free((*cache)->cache_file_name);
+
+ (*cache)->cache_file_name = NULL;
+ }
+
+
+ if ((*cache)->entries)
+ free_sort_list(& ((*cache)->entries));
+
+ (*cache)->magic = 0; /* Invalidate */
+
+ free(*cache);
+ *cache = NULL;
+ }
+
+
+ /* NULL if / without absolute path */
+ static const char * pathname_to_entryname P_((struct last_read_cache * this_last_read,
+ const char * pathname,
+ struct stat * file_stat));
+ static const char * pathname_to_entryname(this_last_read,pathname,file_stat) + struct last_read_cache * this_last_read;
+ const char * pathname;
+ struct stat * file_stat;
+ {
+ const char * name1 = pathname;
+
+ if (LAST_READ_CACHE_magic != this_last_read->magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"pathname_to_entryname",
+ "Bad magic type (last_read_cache)",0);
+
+ if (this_last_read->sys_dir &&
+ in_directory(file_stat,pathname,this_last_read->sys_dir)) {
+
+ char * x = strrchr(pathname,'/');
+
+ DPRINT(Debug,13,(&Debug,
+ "pathname_to_entryname: %s on directory %s",
+ pathname,this_last_read->sys_dir));
+
+ if (x && x[1]) {
+ name1 = x+1;
+
+ DPRINT(Debug,13,(&Debug,", name => %s",
+ name1));
+ }
+ DPRINT(Debug,13,(&Debug,"\n"));
+ }
+
+ if (! name1[0]) {
+ DPRINT(Debug,13,(&Debug,
+ "pathname_to_entryname: %s - empty name\n",
+ pathname));
+ name1 = NULL;
+ } else if ('/' != name1[0] ) {
+
+ const char * x1;
+
+ for (x1 = name1; *x1; x1++) {
+ if ('/' == *x1) {
+ DPRINT(Debug,13,(&Debug,
+ "pathname_to_entryname: %s - invalid name %s\n",
+ pathname,name1));
+ name1 = NULL;
+ goto fail;
+ }
+ }
+ }
+
+ fail:
+ return name1;
+ }
+
+ /* Cache assumed to point correct directory */
+ int have_last_read(this_last_read,pathname,file_stat,last_read_time)
+ struct last_read_cache * this_last_read;
+ const char * pathname;
+ struct stat * file_stat;
+ time_t * last_read_time;
+ {
+ /* this_last_read is from upgrade_last_read() */
+
+ const char * name1 = pathname;
+ int ret = 0;
+
+ if (LAST_READ_CACHE_magic != this_last_read->magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"have_last_read",
+ "Bad magic type (last_read_cache)",0);
+
+ name1 = pathname_to_entryname(this_last_read,pathname,file_stat);
+
+ if (!name1) {
+ DPRINT(Debug,13,(&Debug,
+ "have_last_read: %s: Invalid name\n",
+ pathname));
+ goto fail;
+ }
+
+ if (this_last_read->entries) {
+ union sort_key key;
+ union sort_item res;
+ union sort_item_default def;
+ size_t idx = 0;
+
+ key.str = name1;
+ def.last_read_entry = NULL;
+ res.dummy = NULL;
+
+ if (search_sort_list_item(this_last_read->entries,
+ sort_list_search_normal,
+ key,def,&res,&idx,
+ NULL)) {
+
+ if (res.last_read_entry) {
+ struct last_read_entry * entry = res.last_read_entry;
+
+ DPRINT(Debug,13,(&Debug,
+ "have_last_read: %s: %s found from %s idx %zu\n",
+ pathname,name1,
+ this_last_read->cache_file_name ?
+ this_last_read->cache_file_name : "(no name)", + idx));
+
+ if (LAST_READ_ENTRY_magic != entry->magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"have_last_read",
+ "Bad magic type (last_read_entry)",0);
+
+ if (ison(entry->entry_flags,LAST_READ_valid)) {
+
+ if (FILE_CHANGES_magic != this_last_read->cache_file.magic) + panic("MBX PANIC",__FILE__,__LINE__,"have_last_read",
+ "Bad magic number (file_changes)",0);
+
+ if (file_stat && this_last_read->cache_file.valid) {
+
+ if (this_last_read->cache_file.dev != file_stat->st_dev) {
+
+ DPRINT(Debug,13,(&Debug,
+ "have_last_read: %s: directory %s st_dev %ld != stat dev %ld\n",
+ pathname,
+ this_last_read->sys_dir ?
+ this_last_read->sys_dir :
+ "(default)",
+ (long) this_last_read->cache_file.dev,
+ (long) file_stat->st_dev));
+
+ if (ison(entry->entry_flags, LAST_READ_have_st_ino)) {
+ DPRINT(Debug,13,(&Debug,
+ "have_last_read: %s: idx %zu %s have st_ino -- no match\n",
+ pathname,idx,
+ entry->folder_sys));
+ goto fail_match;
+ }
+
+ } else {
+ if (isoff(entry->entry_flags, LAST_READ_have_st_ino)) {
+ DPRINT(Debug,13,(&Debug,
+ "have_last_read: %s: idx %zu %s have no st_ino -- no match\n",
+ pathname,idx,
+ entry->folder_sys));
+ goto fail_match;
+ }
+
+ if (entry->st_ino != file_stat->st_ino) {
+ DPRINT(Debug,13,(&Debug,
+ "have_last_read: %s: idx %zu %s st_ino %lu != stat ino %lu -- no match\n",
+ pathname,idx,
+ (unsigned long) entry->st_ino, + (unsigned long) file_stat->st_ino,
+ entry->folder_sys));
+
+ goto fail_match;
+ }
+ }
+ }
+
+ if (entry->last_read > 0 &&
+ (time_t)-1 != entry->last_read) {
+ char *X = ctime(& (entry->last_read));
+
+ DPRINT(Debug,13,(&Debug,
+ "have_last_read: %s: entry %zu %s last_read %ld",
+ pathname,idx,
+ entry->folder_sys,
+ (long)entry->last_read));
+
+ if (X) { /* ctime() includes newline */
+ DPRINT(Debug,13,(&Debug," -- %s",X));
+ } else {
+ DPRINT(Debug,13,(&Debug,"\n"));
+ }
+
+ if (last_read_time)
+ *last_read_time = entry->last_read;
+
+ ret = 1;
+ }
+
+
+ } else {
+ DPRINT(Debug,13,(&Debug,
+ "have_last_read: %s: entry %zu %s not valid\n",
+ pathname,idx,
+ entry->folder_sys));
+ }
+
+ fail_match:
+
+ /* Decrements refcount */
+ free_last_read_entry(& res.last_read_entry);
+
+ } else {
+ DPRINT(Debug,13,(&Debug,
+ "have_last_read: %s: %s found from %s idx %zu - search_sort_list_item did not set last_read_entry\n",
+ pathname,name1,
+ this_last_read->cache_file_name ?
+ this_last_read->cache_file_name : "(no name)",
+ idx));
+ }
+
+ } else {
+ DPRINT(Debug,13,(&Debug,
+ "have_last_read: %s: %s not found from %s\n",
+ pathname,name1,
+ this_last_read->cache_file_name ?
+ this_last_read->cache_file_name : "(no name)"));
+ }
+
+ } else {
+ DPRINT(Debug,13,(&Debug,
+ "have_last_read: %s no entries on %s\n",
+ pathname,
+ this_last_read->cache_file_name ?
+ this_last_read->cache_file_name : "(no name)"));
+ }
+
+
+ fail:
+ DPRINT(Debug,13,(&Debug,
+ "have_last_read=%d; pathname=%s",
+ ret,pathname));
+
+ if (last_read_time && *last_read_time > 0 && (time_t)-1 != *last_read_time) {
+ char *X = ctime(last_read_time);
+ DPRINT(Debug,13,(&Debug,
+ " *last_read_time=%ld",
+ *last_read_time));
+
+ if (X) { /* ctime() includes newline */
+ DPRINT(Debug,13,(&Debug," -- %s",X));
+ } else {
+ DPRINT(Debug,13,(&Debug,"\n"));
+ }
+ }
+
+ DPRINT(Debug,13,(&Debug,"\n"));
+
+ return ret;
+ }
+
+ /* Possible allocates new, decrement old refcount if name is changed */
+ int update_last_read(dir_last_read,sys_dir)
+ struct last_read_cache ** dir_last_read;
+ const char * sys_dir;
+ {
+ int cache_changed = 0;
+ int ret = 0;
+
+ const char * resolved_dir = NULL;
+
+ enum last_read_location new_loc = last_read_dir_to_loc(sys_dir,
+ &resolved_dir);
+
+ if (*dir_last_read) {
+ if (LAST_READ_CACHE_magic != (*dir_last_read)->magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"update_last_read",
+ "Bad magic type (last_read_cache)",0);
+
+ DPRINT(Debug,13,(&Debug,
+ "update_last_read: old cache %p",
+ *dir_last_read));
+
+ if ((*dir_last_read)->sys_dir) {
+ DPRINT(Debug,13,(&Debug,"; sys_dir=%s",
+ (*dir_last_read)->sys_dir));
+ }
+ if (last_read_def_cache == *dir_last_read) {
+ DPRINT(Debug,13,(&Debug,"; default cache"));
+ }
+ if ((*dir_last_read)->cache_file_name) {
+ DPRINT(Debug,13,(&Debug,"; cache_file_name=%s",
+ (*dir_last_read)->cache_file_name));
+ }
+ DPRINT(Debug,13,(&Debug,"\n"));
+
+ switch (new_loc) {
+ case read_loc_none: cache_changed = 1; break;
+ case read_loc_dir:
+ if (! (*dir_last_read)->sys_dir ||
+ ! resolved_dir ||
+ ! same_dir_str((*dir_last_read)->sys_dir,
+ resolved_dir))
+ cache_changed = 1;
+ break;
+ case read_loc_def:
+ if ((*dir_last_read)->sys_dir)
+ cache_changed = 1;
+
+ }
+
+ if (cache_changed)
+ free_last_read_cache(dir_last_read);
+
+ } else
+ cache_changed = 1;
+
+ if (cache_changed) {
+
+ if (*dir_last_read)
+ panic("MBX PANIC",__FILE__,__LINE__,"update_last_read",
+ "Cache still set",0);
+
+ if (read_loc_dir == new_loc) {
+ enum syscall_status r;
+
+ r = access(sys_dir,WRITE_ACCESS|EXECUTE_ACCESS);
+
+ switch (r) {
+ int err UNUSED_VAROK;
+ case syscall_error /* -1 */:
+ err = errno;
+
+ DPRINT(Debug,10,(&Debug,
+ "update_last_read: No write access (and search) for %s: %s (errno=%d)\n",
+ sys_dir,strerror(err), err));
+
+ /* No last_read_cache, if directory
+ is not writable and executable (searchable)
+ */
+ ret = 0;
+ goto out;
+ case syscall_success /* 0 */:
+ DPRINT(Debug,10,(&Debug,
+ "update_last_read: %s is accessible\n",
+ sys_dir));
+ break;
+ }
+ }
+
+ /* locate from last_read_dir_cache */
+ /* or last_read_def_cache */
+
+ (*dir_last_read) = give_last_read(sys_dir,
+ new_loc,resolved_dir,
+ last_read_def_existing);
+ }
+
+ if (*dir_last_read) {
+ if (LAST_READ_CACHE_magic != (*dir_last_read)->magic)
+ panic("MBX PANIC",__FILE__,__LINE__,"update_last_read",
+ "Bad magic type (last_read_cache)",0);
+
+ DPRINT(Debug,10,(&Debug,
+ "update_last_read: %s: cache %p",
+ sys_dir,*dir_last_read));
+
+ if ((*dir_last_read)->sys_dir) {
+ DPRINT(Debug,10,(&Debug,"; sys_dir=%s",
+ (*dir_last_read)->sys_dir));
+ }
+ if (last_read_def_cache == *dir_last_read) {
+ DPRINT(Debug,10,(&Debug,"; default cache"));
+ }
+ if ((*dir_last_read)->cache_file_name) {
+ DPRINT(Debug,10,(&Debug,"; cache_file_name=%s",
+ (*dir_last_read)->cache_file_name));
+ }
+
+ ret = 1;
+ } else {
+ DPRINT(Debug,10,(&Debug,
+ "update_last_read: %s: No cache",
+ sys_dir));
+
+ ret = 0;
+ }
+
+ if (cache_changed) {
+ DPRINT(Debug,10,(&Debug,"; cache changed\n"));
+ }
+ DPRINT(Debug,10,(&Debug,"\n"));
+
+ out:
+ DPRINT(Debug,12,(&Debug,
+ "update_last_read=%d%s\n",
+ ret,
+ ret ? " last_read active" : ""));
+
+ return ret;
+ }
+
+
+ /* Increments refcount */
+
+
+ struct last_read_cache * last_read_enabled(use_lastread,cur_folder_sys,
+ oldstat,curstat)
+ enum use_lastread_v use_lastread;
+ char * cur_folder_sys;
+ struct stat * oldstat;
+ struct stat * curstat;
+ {
+ struct last_read_cache *ret = NULL;
+
+ int free_sys_dir = 0;
+ char * sys_dir = stat_file_to_sys_dir(cur_folder_sys,
+ &free_sys_dir);
+ enum last_read_location last_read_loc = read_loc_none;
+ const char * res_dir = NULL;
+
+ enum last_read_default may_create = last_read_def_existing;
+ struct last_read_cache * last_read = NULL;
+
+ DPRINT(Debug,13,(&Debug,
+ "last_read_enabled: use_lastread=%d",
+ use_lastread));
+
+ switch (use_lastread) {
+ case use_lastread_no: DPRINT(Debug,13,(&Debug," use_lastread_no\n")); goto fail;
+ case use_lastread_yes: DPRINT(Debug,13,(&Debug," use_lastread_yes"));
+ may_create = last_read_def_create;
+ break;
+ case use_lastread_auto: DPRINT(Debug,13,(&Debug," use_lastread_auto")); break;
+ case use_lastread_existing: DPRINT(Debug,13,(&Debug," use_lastread_existing")); break;
+ case NUM_use_lastread: break;
+ }
+
+ DPRINT(Debug,13,(&Debug,", cur_folder_sys=%s", cur_folder_sys));
+
+ if (oldstat) {
+ DPRINT(Debug,13,(&Debug,
+ ", oldstat dev/ino=%lu/%lu atime=%ld",
+ (unsigned long)(oldstat->st_dev),
+ (unsigned long)(oldstat->st_ino),
+ (long)oldstat->st_atime));
+ }
+ if (curstat) {
+ DPRINT(Debug,13,(&Debug,
+ ", curstat dev/ino=%lu/%lu atime=%ld",
+ (unsigned long)(curstat->st_dev),
+ (unsigned long)(curstat->st_ino),
+ (long)curstat->st_atime));
+ }
+
+ if (oldstat && curstat) {
+ if (oldstat->st_dev == curstat->st_dev &&
+ oldstat->st_ino == curstat->st_ino) {
+ if (oldstat->st_atime == curstat->st_atime){
+ DPRINT(Debug,13,(&Debug,", time stampt not updated"));
+ if (use_lastread_auto == use_lastread) {
+ may_create = last_read_def_create;
+ DPRINT(Debug,13,(&Debug,", use last read"));
+ }
+ } else if (oldstat->st_atime < curstat->st_atime) {
+ DPRINT(Debug,13,(&Debug,", time stamp advanced"));
+ }
+ } else {
+ DPRINT(Debug,13,(&Debug,", file changed"));
+ }
+ }
+
+ DPRINT(Debug,13,(&Debug,"; sys_dir=%s\n",sys_dir));
+
+ last_read_loc = last_read_dir_to_loc(sys_dir,&res_dir);
+
+ DPRINT(Debug,13,(&Debug,
+ "last_read_enabled: sys_dir=%s => location %d",
+ sys_dir,
+ last_read_loc));
+
+ switch (last_read_loc) {
+ case read_loc_none: DPRINT(Debug,13,(&Debug," read_loc_none\n")); goto fail;
+ case read_loc_dir: DPRINT(Debug,13,(&Debug," read_loc_dir")); break;
+ case read_loc_def: DPRINT(Debug,13,(&Debug," read_loc_def")); break;
+ }
+
+ if (res_dir) {
+ DPRINT(Debug,13,(&Debug,", res_dir=%s",res_dir));
+ }
+ DPRINT(Debug,13,(&Debug,"\n"));
+
+ if (read_loc_dir == last_read_loc) {
+
+ enum syscall_status r = access(sys_dir,WRITE_ACCESS|EXECUTE_ACCESS);
+
+ switch (r) {
+ int err UNUSED_VAROK;
+ case syscall_error /* -1 */:
+ err = errno;
+
+ DPRINT(Debug,10,(&Debug,
+ "last_read_enabled: No write access (and search) for %s: %s (errno=%d)\n",
[continued in next message]
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)