static int max_backup_version(char *file, char *dir) { DIR *dirp; struct dirent *dp; int highest_version; int this_version; int file_name_length; dirp = opendir (dir); if (!dirp) return 0; highest_version = 0; file_name_length = strlen (file); while ((dp = readdir (dirp)) != 0) { if (!REAL_DIR_ENTRY (dp) || NLENGTH (dp) <= file_name_length) continue; this_version = version_number (file, dp->d_name, file_name_length); if (this_version > highest_version) highest_version = this_version; } closedir (dirp); return highest_version; }
static int highest_version ( char * filename, char * dirname) { DIR * dirp = opendir (dirname); struct dirent * dp = NULL; int highestVersion; if (!dirp) { highestVersion = 0; } else { int this_version; unsigned int file_name_length = strlen(filename); highestVersion = 0; while ((dp = readdir (dirp)) != 0) { if (!REAL_DIR_ENTRY (dp) || NAMLEN (dp) <= file_name_length + 2) { continue; } this_version = version_number (filename, dp->d_name, file_name_length); if (this_version > highestVersion) { highestVersion = this_version; } } closedir (dirp); } return highestVersion; }
static enum numbered_backup_result numbered_backup (char **buffer, size_t buffer_size, size_t filelen) { enum numbered_backup_result result = BACKUP_IS_NEW; DIR *dirp; struct dirent *dp; char *buf = *buffer; size_t versionlenmax = 1; char *base = last_component (buf); size_t base_offset = base - buf; size_t baselen = base_len (base); /* Temporarily modify the buffer into its parent directory name, open the directory, and then restore the buffer. */ char tmp[sizeof "."]; memcpy (tmp, base, sizeof "."); strcpy (base, "."); dirp = opendir (buf); memcpy (base, tmp, sizeof "."); strcpy (base + baselen, ".~1~"); if (!dirp) return result; while ((dp = readdir (dirp)) != NULL) { char const *p; char *q; bool all_9s; size_t versionlen; size_t new_buflen; if (! REAL_DIR_ENTRY (dp) || _D_EXACT_NAMLEN (dp) < baselen + 4) continue; if (memcmp (buf + base_offset, dp->d_name, baselen + 2) != 0) continue; p = dp->d_name + baselen + 2; /* Check whether this file has a version number and if so, whether it is larger. Use string operations rather than integer arithmetic, to avoid problems with integer overflow. */ if (! ('1' <= *p && *p <= '9')) continue; all_9s = (*p == '9'); for (versionlen = 1; ISDIGIT (p[versionlen]); versionlen++) all_9s &= (p[versionlen] == '9'); if (! (p[versionlen] == '~' && !p[versionlen + 1] && (versionlenmax < versionlen || (versionlenmax == versionlen && memcmp (buf + filelen + 2, p, versionlen) <= 0)))) continue; /* This directory has the largest version number seen so far. Append this highest numbered extension to the file name, prepending '0' to the number if it is all 9s. */ versionlenmax = all_9s + versionlen; result = (all_9s ? BACKUP_IS_LONGER : BACKUP_IS_SAME_LENGTH); new_buflen = filelen + 2 + versionlenmax + 1; if (buffer_size <= new_buflen) { buf = xnrealloc (buf, 2, new_buflen); buffer_size = new_buflen * 2; } q = buf + filelen; *q++ = '.'; *q++ = '~'; *q = '0'; q += all_9s; memcpy (q, p, versionlen + 2); /* Add 1 to the version number. */ q += versionlen; while (*--q == '9') *q = '0'; ++*q; } closedir (dirp); *buffer = buf; return result; }
/* Like `glob', but PATTERN is a final pathname component, and matches are searched for in DIRECTORY. The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. The GLOB_APPEND flag is assumed to be set (always appends). */ static int glob_in_dir(const char *pattern, const char *directory, int flags, errfunc_t errfunc, glob_t *pglob) { #ifdef WIN32 HANDLE stream; WIN32_FIND_DATA findinfo; int first = 1; #else void *stream; #endif struct globlink { struct globlink *next; char *name; }; struct globlink *names = NULL; size_t nfound = 0; DEBUGOUT(_LtDebug(__FILE__, NULL, "glob_in_dir(%s, %s, %i,)\n", pattern, directory, flags)); if (!glob_pattern_p(pattern, !(flags & GLOB_NOESCAPE))) { stream = NULL; flags |= GLOB_NOCHECK; } else { flags |= GLOB_MAGCHAR; #ifdef WIN32 stream = FindFirstFile(directory, &findinfo); if (stream == INVALID_HANDLE_VALUE) stream = NULL; #else stream = (__glob_opendir_hook ? (*__glob_opendir_hook) (directory) : (void *) opendir(directory)); #endif if (stream == NULL) { if ((errfunc != NULL && (*errfunc) (directory, errno)) || (flags & GLOB_ERR)) return GLOB_ABEND; } else while (1) { const char *name; size_t len; #ifdef WIN32 if (first) { /* The FindFirstFile call actaully reads the first one */ first = 0; } else { if (!FindNextFile(stream, &findinfo)) break; } name = findinfo.cFileName; len = 0; #else if (__glob_readdir_hook) { name = (*__glob_readdir_hook) (stream); if (name == NULL) break; len = 0; } else { struct dirent *d = readdir((DIR *) stream); if (d == NULL) break; DEBUGOUT(_LtDebug0(__FILE__, NULL, "glob_in_dir(%s)\n", d->d_name)); if (!REAL_DIR_ENTRY(d)) { DEBUGOUT(_LtDebug0(__FILE__, NULL, "glob_in_dir() continue\n")); continue; } name = d->d_name; #ifdef HAVE_D_NAMLEN len = d->d_namlen; #else len = 0; #endif } #endif if (_Lesstif_fnmatch(pattern, name, (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)) == 0) { struct globlink *new_w = (struct globlink *)XtMalloc(sizeof(struct globlink)); if (len == 0) len = strlen(name); new_w->name = (char *)XtMalloc(len + ((flags & GLOB_MARK) ? 1 : 0) + 1); if (new_w->name == NULL) goto memory_error; memcpy((void *) new_w->name, name, len); new_w->name[len] = '\0'; new_w->next = names; names = new_w; ++nfound; } else { DEBUGOUT(_LtDebug0(__FILE__, NULL, "glob_in_dir() failed fnmatch\n")); } } } DEBUGOUT(_LtDebug0(__FILE__, NULL, "glob_in_dir() found %d\n", nfound)); if (nfound == 0 && (flags & GLOB_NOCHECK)) { size_t len = strlen(pattern); nfound = 1; names = (struct globlink *)XtMalloc(sizeof(struct globlink)); names->next = NULL; names->name = (char *)XtMalloc(len + 1); if (names->name == NULL) goto memory_error; memcpy(names->name, pattern, len); names->name[len] = '\0'; } pglob->gl_pathv = (char **)XtRealloc((char *)pglob->gl_pathv, (pglob->gl_pathc + ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + nfound + 1) * sizeof(char *)); if (pglob->gl_pathv == NULL) goto memory_error; if (flags & GLOB_DOOFFS) while (pglob->gl_pathc < pglob->gl_offs) pglob->gl_pathv[pglob->gl_pathc++] = NULL; while (names != NULL) { struct globlink *next = names->next; pglob->gl_pathv[pglob->gl_pathc++] = names->name; XtFree((char *)names); names = next; } pglob->gl_pathv[pglob->gl_pathc] = NULL; pglob->gl_flags = flags; if (stream != NULL) { int save = errno; #ifdef WIN32 FindClose(stream); #else if (__glob_closedir_hook) (*__glob_closedir_hook) (stream); else closedir((DIR *) stream); #endif errno = save; } return nfound == 0 ? GLOB_NOMATCH : 0; memory_error: { int save = errno; #ifdef WIN32 FindClose(stream); #else if (__glob_closedir_hook) (*__glob_closedir_hook) (stream); else closedir((DIR *) stream); #endif errno = save; } while (names != NULL) { if (names->name != NULL) XtFree((char *) names->name); names = names->next; } if (names) XtFree((char *)names); return GLOB_NOSPACE; } /* glob_in_dir() */