static INT64_T chirp_fs_confuga_pread(int fd, void *buffer, INT64_T length, INT64_T offset) { int rc; size_t n; SETUP_FILE if (offset < 0) CATCH(EINVAL); switch (open_files[fd].type) { case CHIRP_FS_CONFUGA_REPL_READ: CATCH_CONFUGA(confuga_replica_pread(open_files[fd].f.replica, buffer, length, &n, offset, STOPTIME)); break; case CHIRP_FS_CONFUGA_META_READ: if ((size_t)offset < buffer_pos(&open_files[fd].f.metadata)) { n = MIN((size_t)length, buffer_pos(&open_files[fd].f.metadata)-(size_t)offset); memcpy(buffer, buffer_tostring(&open_files[fd].f.metadata)+offset, n); } else { n = 0; } break; default: CATCH(EBADF); } rc = 0; goto out; out: if (rc) { return (errno = rc, -1); } else { return n; /* N.B. return n on success */ } }
/* * Get a filename in cache for given md5sum. */ const char *filecache_getfilename(TARGET *t, MD5SUM sum, const char* extension) { BUFFER buff; size_t pos; const char *cachedir; const char* result; cachedir = filecache_getpath(t); /* if no cachedir, no cachefiles */ if (cachedir==NULL) { return NULL; } /* put the cachedir in front of buffer */ buffer_init(&buff); buffer_addstring(&buff, cachedir, strlen(cachedir)); buffer_addchar(&buff, '/'); pos = buffer_pos(&buff); buffer_addstring(&buff, "000/", 4); /* add use md5 as filename */ buffer_addstring(&buff, md5tostring(sum), 32); if (extension) buffer_addstring(&buff, extension, strlen(extension)); buffer_addchar(&buff, 0); buffer_setpos(&buff, pos); buffer_putstring(&buff, buffer_ptr(&buff) + pos + 4, 3); result = newstr(buffer_ptr(&buff)); buffer_free(&buff); return result; }
static void do_debug(INT64_T flags, const char *fmt, va_list args) { buffer_t B; char ubuf[1<<16]; buffer_init(&B); buffer_ubuf(&B, ubuf, sizeof(ubuf)); buffer_max(&B, sizeof(ubuf)); if (debug_write == debug_file_write || debug_write == debug_stderr_write || debug_write == debug_stdout_write) { struct timeval tv; struct tm *tm; gettimeofday(&tv, 0); tm = localtime(&tv.tv_sec); buffer_putfstring(&B, "%04d/%02d/%02d %02d:%02d:%02d.%02ld ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (long) tv.tv_usec / 10000); buffer_putfstring(&B, "%s[%d] ", debug_program_name, getpid()); } /* Parrot prints debug messages for children: */ if (getpid() != debug_getpid()) { buffer_putfstring(&B, "<child:%d> ", (int)debug_getpid()); } buffer_putfstring(&B, "%s: ", debug_flags_to_name(flags)); buffer_putvfstring(&B, fmt, args); while(isspace(buffer_tostring(&B)[buffer_pos(&B)-1])) buffer_rewind(&B, buffer_pos(&B)-1); /* chomp whitespace */ buffer_putliteral(&B, "\n"); debug_write(flags, buffer_tostring(&B)); if(terminal_available && (flags & (D_ERROR | D_NOTICE | D_FATAL))) { if(debug_write != debug_stderr_write || !isatty(STDERR_FILENO)) { if(!terminal_f) { if((terminal_f = fopen(terminal_path, "a")) == NULL) { /* print to wherever stderr is pointing that we could not open the terminal. */ terminal_available = 0; } } } if(terminal_f) fprintf(terminal_f, "%s", buffer_tostring(&B)); } buffer_free(&B); }
int path_find (buffer_t *B, const char *dir, const char *pattern, int recursive) { int rc=0; buffer_t path; buffer_init(&path); if (buffer_printf(&path, "%s/", dir) == -1) goto out; rc = find(B, buffer_pos(&path), &path, pattern, recursive); out: buffer_free(&path); return rc; }
static void update_blacklisted_workers( struct batch_queue *queue, struct list *masters_list ) { if(!masters_list || list_size(masters_list) < 1) return; buffer_t b; struct jx *j; buffer_init(&b); const char *sep = ""; list_first_item(masters_list); while((j=list_next_item(masters_list))) { struct jx *blacklisted = jx_lookup(j,"workers_blacklisted"); if(!blacklisted) { continue; } if(jx_istype(blacklisted, JX_STRING)) { buffer_printf(&b, "%s%s", sep, blacklisted->u.string_value); sep = " "; } if(jx_istype(blacklisted, JX_ARRAY)) { struct jx *item; for (void *i = NULL; (item = jx_iterate_array(blacklisted, &i));) { if(jx_istype(item, JX_STRING)) { buffer_printf(&b, "%s%s", sep, item->u.string_value); sep = " "; } } } } if(buffer_pos(&b) > 0) { batch_queue_set_option(queue, "workers-blacklisted", buffer_tostring(&b)); } else { batch_queue_set_option(queue, "workers-blacklisted", NULL); } buffer_free(&b); }
static INT64_T chirp_fs_confuga_pwrite(int fd, const void *buffer, INT64_T length, INT64_T offset) { int rc; size_t n; SETUP_FILE if (length < 0 || offset < 0) CATCH(EINVAL); switch (open_files[fd].type) { case CHIRP_FS_CONFUGA_FILE_WRITE: { if ((confuga_off_t)offset != open_files[fd].f.file.size) CATCH(EINVAL); /* do not allow random writes */ CATCH_CONFUGA(confuga_file_write(open_files[fd].f.file.file, buffer, length, &n, STOPTIME)); open_files[fd].f.file.size += n; break; } case CHIRP_FS_CONFUGA_META_WRITE: if ((size_t)offset != buffer_pos(&open_files[fd].f.metadata)) CATCH(EINVAL); /* do not allow random writes */ CATCHUNIX(buffer_putlstring(&open_files[fd].f.metadata, buffer, length)); n = length; break; default: CATCH(EBADF); } rc = 0; goto out; out: if (rc) { return (errno = rc, -1); } else { return n; /* N.B. return n on success */ } }
static int find (buffer_t *B, const size_t base, buffer_t *path, const char *pattern, int recursive) { int rc = 0; DIR *D = opendir(buffer_tostring(path)); if (D) { struct dirent *entry; size_t current = buffer_pos(path); while ((entry = readdir(D))) { struct stat buf; if (buffer_putstring(path, entry->d_name) == -1) goto failure; /* N.B. We don't use FNM_PATHNAME, so `*.c' matches `foo/bar.c' */ if (fnmatch(pattern, buffer_tostring(path)+base, 0) == 0) { if (buffer_printf(B, "%s%c", buffer_tostring(path), 0) == -1) goto failure; /* NUL padded */ rc += 1; } if (recursive && strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..") && stat(buffer_tostring(path), &buf) == 0 && S_ISDIR(buf.st_mode)) { if (buffer_putliteral(path, "/") == -1) goto failure; int found = find(B, base, path, pattern, recursive); if (found == -1) goto failure; else if (found > 0) rc += found; } buffer_rewind(path, current); } } /* else skip */ goto out; failure: rc = -1; goto out; out: if (D) closedir(D); return rc; }
LIST * var_expand( LIST *prefix, const char *in, const char *end, LOL *lol, int cancopyin ) { BUFFER buff; const char *inp = in; int depth; size_t save_buffer_pos, ov_save_buffer_pos; int literal = 0; if( DEBUG_VAREXP ) printf( "expand '%.*s'\n", end - in, in ); /* This gets alot of cases: $(<) and $(>) */ if( end - in == 4 && in[0] == '$' && in[1] == leftParen && in[3] == rightParen ) { switch( in[2] ) { case '1': case '<': return list_copy( prefix, lol_get( lol, 0 ) ); case '2': case '>': return list_copy( prefix, lol_get( lol, 1 ) ); } } buffer_init( &buff ); /* Just try simple copy of in to out. */ while( in < end ) { char ch = *in++; buffer_addchar( &buff, ch ); if( ch == '$' && *in == leftParen ) goto expand; #ifdef OPT_EXPAND_LITERALS_EXT if( ch == '@' && *in == leftParen ) { literal = 1; goto expand; } if( ch == '@' && in[0] == '$' && in[1] == leftParen ) { ++in; literal = 1; goto expand; } #endif } /* No variables expanded - just add copy of input string to list. */ /* Cancopyin is an optimization: if the input was already a list */ /* item, we can use the copystr() to put it on the new list. */ /* Otherwise, we use the slower newstr(). */ buffer_putchar( &buff, 0 ); if( cancopyin ) { LIST *new_list = list_append( prefix, inp, 1 ); buffer_free( &buff ); return new_list; } else { LIST *new_list = list_append( prefix, buffer_ptr( &buff ), 0 ); buffer_free( &buff ); return new_list; } expand: /* * Input so far (ignore blanks): * * stuff-in-outbuf $(variable) remainder * ^ ^ * in end * Output so far: * * stuff-in-outbuf $ * ^ ^ * out_buf out * * * We just copied the $ of $(...), so back up one on the output. * We now find the matching close paren, copying the variable and * modifiers between the $( and ) temporarily into out_buf, so that * we can replace :'s with MAGIC_COLON. This is necessary to avoid * being confused by modifier values that are variables containing * :'s. Ugly. */ depth = 1; buffer_deltapos( &buff, -1 ); save_buffer_pos = buffer_pos( &buff ); in++; while( in < end && depth ) { char ch = *in++; buffer_addchar( &buff, ch ); if ( ch == leftParen ) { depth++; } else if ( ch == rightParen ) { depth--; } else { switch( ch ) { case ':': buffer_deltapos( &buff, -1 ); buffer_addchar( &buff, MAGIC_COLON ); break; case '[': buffer_deltapos( &buff, -1 ); buffer_addchar( &buff, MAGIC_LEFT ); break; case ']': buffer_deltapos( &buff, -1 ); buffer_addchar( &buff, MAGIC_RIGHT ); break; } } } /* Copied ) - back up. */ buffer_deltapos( &buff, -1 ); ov_save_buffer_pos = buffer_pos( &buff ); buffer_setpos( &buff, save_buffer_pos ); /* * Input so far (ignore blanks): * * stuff-in-outbuf $(variable) remainder * ^ ^ * in end * Output so far: * * stuff-in-outbuf variable * ^ ^ ^ * out_buf out ov * * Later we will overwrite 'variable' in out_buf, but we'll be * done with it by then. 'variable' may be a multi-element list, * so may each value for '$(variable element)', and so may 'remainder'. * Thus we produce a product of three lists. */ { LIST *variables = 0; LIST *remainder = 0; LISTITEM *vars; /* Recursively expand variable name & rest of input */ if( save_buffer_pos < ov_save_buffer_pos ) variables = var_expand( L0, buffer_posptr( &buff ), buffer_ptr( &buff ) + ov_save_buffer_pos, lol, 0 ); if( in < end ) remainder = var_expand( L0, in, end, lol, 0 ); /* Now produce the result chain */ /* For each variable name */ for( vars = list_first(variables); vars; vars = list_next( vars ) ) { LIST *value, *evalue = 0; LISTITEM* valueSliceStart = NULL; #ifdef OPT_EXPAND_LITERALS_EXT LIST *origvalue = 0; #endif char *colon; char *bracket; BUFFER varnamebuff; int sub1 = 0, sub2 = -1; VAR_EDITS edits; memset(&edits, 0, sizeof(VAR_EDITS)); if (leftParen == '{') { edits.empty.ptr = ""; edits.empty.len = 0; } /* Look for a : modifier in the variable name */ /* Must copy into varname so we can modify it */ buffer_init( &varnamebuff ); buffer_addstring( &varnamebuff, list_value(vars), strlen( list_value(vars) ) ); buffer_addchar( &varnamebuff, 0 ); if( ( colon = strchr( buffer_ptr( &varnamebuff ), MAGIC_COLON ) ) ) { *colon = '\0'; var_edit_parse( colon + 1, &edits ); } /* Look for [x-y] and [x-] subscripting */ /* sub1 is x (0 default) */ /* sub2 is length (-1 means forever) */ if( ( bracket = strchr( buffer_ptr( &varnamebuff ), MAGIC_LEFT ) ) ) { char *dash; if( ( dash = strchr( bracket + 1, '-' ) ) ) *dash = '\0'; sub1 = atoi( bracket + 1 ) - 1; if( !dash ) sub2 = 1; else if( !dash[1] || dash[1] == MAGIC_RIGHT ) sub2 = -1; else sub2 = atoi( dash + 1 ) - sub1; *bracket = '\0'; } /* Get variable value, specially handling $(<), $(>), $(n) */ #ifdef OPT_EXPAND_LITERALS_EXT if ( !literal ) #endif { const char* varname = buffer_ptr( &varnamebuff ); if( varname[0] == '<' && !varname[1] ) value = lol_get( lol, 0 ); else if( varname[0] == '>' && !varname[1] ) value = lol_get( lol, 1 ); else if( varname[0] >= '1' && varname[0] <= '9' && !varname[1] ) value = lol_get( lol, varname[0] - '1' ); else if ( edits.targetsetting ) { TARGET* t = bindtarget(edits.targetname.ptr); SETTINGS* settings = quicksettingslookup(t, varname); if (settings) value = list_copy(L0, settings->value); else value = L0; } else value = var_get( varname ); } #ifdef OPT_EXPAND_LITERALS_EXT else { origvalue = value = list_append( L0, buffer_ptr( &varnamebuff ), 0 ); } #endif /* The fast path: $(x) - just copy the variable value. */ /* This is only an optimization */ if( buffer_isempty( &buff ) && !bracket && !colon && in == end ) { prefix = list_copy( prefix, value ); buffer_free( &buff ); continue; } /* Handle start subscript */ valueSliceStart = list_first(value); while(sub1 > 0 && valueSliceStart) { sub1 -= 1; valueSliceStart = list_next(valueSliceStart); } /* Empty w/ :E=default? */ if( !valueSliceStart && (colon || leftParen == '{') && edits.empty.ptr ) { evalue = value = list_append( L0, edits.empty.ptr, 0 ); valueSliceStart = list_first(value); } #ifdef OPT_EXPAND_LITERALS_EXT if ( colon && edits.expandliteral ) { LOL lol; char const* string = list_value(list_first(value)); LIST *newvalue = var_expand( L0, string, string + strlen( string ), &lol, 0 ); if ( origvalue ) { list_free( origvalue ); origvalue = 0; } value = newvalue; valueSliceStart = list_first(value); sub2 = -1; } #endif #ifdef OPT_EXPAND_FILEGLOB_EXT if ( edits.wildcard ) { LIST *newl = L0; for( ; valueSliceStart; valueSliceStart = list_next( valueSliceStart ) ) { LIST *foundfiles = L0; fileglob* glob; /* Handle end subscript (length actually) */ if( sub2 >= 0 && --sub2 < 0 ) break; glob = fileglob_Create( list_value(valueSliceStart) ); while ( fileglob_Next( glob ) ) { foundfiles = list_append( foundfiles, fileglob_FileName( glob ) + edits.wildcard_remove_prepend.len, 0 ); } fileglob_Destroy( glob ); /* TODO: Efficiency: Just append to newl above? */ newl = list_copy( newl, foundfiles ); list_free( foundfiles ); } if ( origvalue ) { list_free( origvalue ); origvalue = 0; } value = newl; origvalue = value; valueSliceStart = list_first(value); } #endif /* For each variable value */ for( ; valueSliceStart; valueSliceStart = list_next( valueSliceStart ) ) { LISTITEM *rem; size_t save_buffer_pos; size_t end_buffer_pos; const char *valuestring; /* Handle end subscript (length actually) */ if( sub2 >= 0 && --sub2 < 0 ) break; /* Apply : mods, if present */ save_buffer_pos = buffer_pos( &buff ); valuestring = list_value(valueSliceStart); #ifdef OPT_EXPAND_BINDING_EXT if( colon && edits.expandbinding ) { SETTINGS *expandText; TARGET *t = bindtarget( valuestring ); expandText = quicksettingslookup( t, "EXPAND_TEXT" ); if ( expandText && list_first(expandText->value) ) { valuestring = list_value(list_first(expandText->value)); } else { if( t->binding == T_BIND_UNBOUND ) { t->boundname = search_using_target_settings( t, t->name, &t->time ); t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; } valuestring = t->boundname; } } #endif if( colon && edits.filemods ) { var_edit_file( valuestring, &buff, &edits ); } else { buffer_addstring( &buff, valuestring, strlen( valuestring ) + 1 ); } buffer_setpos( &buff, save_buffer_pos ); if( colon && ( edits.upshift || edits.downshift ) ) var_edit_shift( buffer_posptr( &buff ), &edits ); #ifdef OPT_SLASH_MODIFIERS_EXT if( colon && ( edits.fslash || edits.bslash ) ) var_edit_slash( buffer_posptr( &buff ), &edits ); #endif #ifdef OPT_EXPAND_ESCAPE_PATH_EXT if ( colon && edits.escapepath ) { const char* ptr = buffer_posptr( &buff ); const char* endptr = ptr + strlen( ptr ); BUFFER escapebuff; buffer_init( &escapebuff ); save_buffer_pos = buffer_pos( &buff ); #ifdef NT while ( ptr != endptr && *ptr != ' ' && *ptr != '/' ) ++ptr; if (*ptr == ' ' || *ptr == '/' ) { buffer_addchar( &escapebuff, '"' ); buffer_addstring( &escapebuff, buffer_posptr( &buff ), endptr - buffer_posptr( &buff ) ); buffer_addchar( &escapebuff, '"' ); buffer_addchar( &escapebuff, 0 ); buffer_addstring( &buff, buffer_ptr( &escapebuff ), buffer_pos( &escapebuff ) ); } #else while ( ptr != endptr ) { if ( *ptr == ' ' || *ptr == '\\' || *ptr == leftParen || *ptr == rightParen || *ptr == '"' ) { buffer_addchar( &escapebuff, '\\' ); } buffer_addchar( &escapebuff, *ptr ); ++ptr; } buffer_addchar( &escapebuff, 0 ); buffer_addstring( &buff, buffer_ptr( &escapebuff ), buffer_pos( &escapebuff ) ); #endif buffer_setpos( &buff, save_buffer_pos ); buffer_free( &escapebuff ); } #endif /* Handle :J=joinval */ /* If we have more values for this var, just */ /* keep appending them (with the join value) */ /* rather than creating separate LIST elements. */ if( colon && edits.join.ptr && ( list_next( valueSliceStart ) || list_next( vars ) ) ) { buffer_setpos( &buff, buffer_pos( &buff ) + strlen( buffer_posptr( &buff ) ) ); buffer_addstring( &buff, edits.join.ptr, strlen( edits.join.ptr ) + 1 ); buffer_deltapos( &buff, -1 ); continue; } /* If no remainder, append result to output chain. */ if( in == end ) { prefix = list_append( prefix, buffer_ptr( &buff ), 0 ); continue; } /* For each remainder, append the complete string */ /* to the output chain. */ /* Remember the end of the variable expansion so */ /* we can just tack on each instance of 'remainder' */ save_buffer_pos = buffer_pos( &buff ); end_buffer_pos = strlen( buffer_ptr( &buff ) ); buffer_setpos( &buff, end_buffer_pos ); for( rem = list_first(remainder); rem; rem = list_next( rem ) ) { buffer_addstring( &buff, list_value(rem), strlen( list_value(rem) ) + 1 ); buffer_setpos( &buff, end_buffer_pos ); prefix = list_append( prefix, buffer_ptr( &buff ), 0 ); } buffer_setpos( &buff, save_buffer_pos ); } /* Toss used empty */ if( evalue ) list_free( evalue ); #ifdef OPT_EXPAND_LITERALS_EXT if ( origvalue ) list_free( origvalue ); #endif #ifdef OPT_EXPAND_INCLUDES_EXCLUDES_EXT if ( edits.includes_excludes ) { LIST *newl = L0; LISTITEM* l; LIST *origprefix = prefix; int hasInclude = 0; if ( !regexhash ) regexhash = hashinit( sizeof(regexdata), "regex" ); { LISTITEM *inex = list_first(edits.includes_excludes); while ( inex ) { char mod = list_value(inex)[0]; inex = list_next( inex ); if ( mod == 'I' ) { hasInclude = 1; } } } for (l = list_first(prefix) ; l; l = list_next( l ) ) { LISTITEM *inex = list_first(edits.includes_excludes); int remove = hasInclude; while ( inex ) { char mod = list_value(inex)[0]; regexp *re; regexdata data, *d = &data; inex = list_next( inex ); data.name = list_value(inex); if( !hashcheck( regexhash, (HASHDATA **)&d ) ) { d->re = jam_regcomp( list_value(inex) ); (void)hashenter( regexhash, (HASHDATA **)&d ); } re = d->re; inex = list_next( inex ); if ( mod == 'X' ) { if( jam_regexec( re, list_value(l) ) ) remove = 1; } else if ( mod == 'I' ) { if( jam_regexec( re, list_value(l) ) ) remove = 0; } } if ( !remove ) newl = list_append( newl, list_value(l), 1 ); } /* TODO: Efficiency: Just modify prefix? */ list_free( origprefix ); prefix = newl; } #endif //#ifdef OPT_EXPAND_LITERALS_EXT // buffer_free( &buff ); //#endif #ifdef OPT_EXPAND_INCLUDES_EXCLUDES_EXT list_free( edits.includes_excludes ); #endif } /* variables & remainder were gifts from var_expand */ /* and must be freed */ list_free( variables ); list_free( remainder ); if( DEBUG_VAREXP ) { printf( "expanded to " ); list_print( prefix ); printf( "\n" ); } buffer_free( &buff ); return prefix; } }
int _fileglob_GlobHelper(fileglob* self, const char* inPattern) { fileglob_Context* context = self->context; int hasWildcard; int found; Setup: if (!context) { context = (fileglob_Context*)self->allocFunction(self->userData, NULL, sizeof(fileglob_Context)); context->prev = self->context; #if defined(WIN32) context->handle = INVALID_HANDLE_VALUE; #else context->dirp = NULL; context->hasattr = 0; context->statted = 0; #endif context->pattern = NULL; context->iterNode = NULL; context->directoryListHead = context->directoryListTail = 0; context->basePathLastSlashPos = 0; buffer_initwithalloc(&context->patternBuf, self->allocFunction, self->userData); buffer_addstring(&context->patternBuf, inPattern, strlen(inPattern) + 1); buffer_initwithalloc(&context->basePath, self->allocFunction, self->userData); buffer_initwithalloc(&context->matchPattern, self->allocFunction, self->userData); self->context = context; if (context->prev == NULL) return 1; } DoRecursion: found = 1; if (!context->pattern) { char* pattern; context->basePathEndPos = context->basePathLastSlashPos = 0; context->recurseAtPos = (size_t)-1; // Split the path into base path and pattern to match against. hasWildcard = 0; for (pattern = buffer_ptr(&context->patternBuf); *pattern != '\0'; ++pattern) { char ch = *pattern; // Is it a '?' ? if (ch == '?') hasWildcard = 1; // Is it a '*' ? else if (ch == '*') { hasWildcard = 1; // Is there a '**'? if (pattern[1] == '*') { // If we're just starting the pattern or the characters immediately // preceding the pattern are a drive letter ':' or a directory path // '/', then set up the internals for later recursion. if (pattern == buffer_ptr(&context->patternBuf) || pattern[-1] == '/' || pattern[-1] == ':') { char ch2 = pattern[2]; if (ch2 == '/') { context->recurseAtPos = pattern - buffer_ptr(&context->patternBuf); memcpy(pattern, pattern + 3, strlen(pattern) - 2); buffer_deltapos(&context->patternBuf, -3); } else if (ch2 == '\0') { context->recurseAtPos = pattern - buffer_ptr(&context->patternBuf); *pattern = '\0'; } } } } // Is there a '/' or ':' in the pattern at this location? if (ch == '/' || ch == ':') { if (hasWildcard) break; else { if (pattern[1]) context->basePathLastSlashPos = pattern - buffer_ptr(&context->patternBuf) + 1; context->basePathEndPos = pattern - buffer_ptr(&context->patternBuf) + 1; } } } context->pattern = pattern; // Copy the directory down. context->basePathLen = context->basePathEndPos; buffer_reset(&context->basePath); buffer_addstring(&context->basePath, buffer_ptr(&context->patternBuf), context->basePathLen); buffer_addchar(&context->basePath, 0); if (context->iterNode) { context->matchFiles = *context->pattern == 0; goto NextDirectory; } } #if defined(WIN32) if (context->handle == INVALID_HANDLE_VALUE) { #else if (!context->dirp && !context->statted) { #endif size_t matchLen; // Did we make it to the end of the pattern? If so, we should match files, // since there were no slashes encountered. context->matchFiles = *context->pattern == 0; // Copy the wildcard matching string. matchLen = (context->pattern - buffer_ptr(&context->patternBuf)) - context->basePathLen; buffer_reset(&context->matchPattern); buffer_addstring(&context->matchPattern, buffer_ptr(&context->patternBuf) + context->basePathLen, matchLen + 1); buffer_deltapos(&context->matchPattern, -1); if (*buffer_posptr(&context->matchPattern) == '/') { buffer_deltapos(&context->matchPattern, 1); buffer_addchar(&context->matchPattern, 0); } #if defined(WIN32) // Do the file search with *.* in the directory specified in basePattern. buffer_setpos(&context->basePath, context->basePathEndPos); buffer_addstring(&context->basePath, "*.*", 4); // Start the find. context->handle = FindFirstFile(buffer_ptr(&context->basePath), &context->fd); if (context->handle == INVALID_HANDLE_VALUE) { found = 0; } #else // Start the find. buffer_setpos(&context->basePath, context->basePathEndPos); buffer_addchar(&context->basePath, 0); context->dirp = opendir(buffer_ptr(&context->basePath)[0] ? buffer_ptr(&context->basePath) : "."); if (!context->dirp) { found = 0; } else { context->dp = readdir(context->dirp); found = context->dp != NULL; } #endif // Clear out the *.* so we can use the original basePattern string. buffer_setpos(&context->basePath, context->basePathEndPos); buffer_putchar(&context->basePath, 0); } else { goto NextFile; } // Any files found? #if defined(WIN32) if (context->handle != INVALID_HANDLE_VALUE) { #else if (context->dirp) { #endif for (;;) { #if defined(WIN32) char* filename = context->fd.cFileName; #else char* filename = context->dp->d_name; context->hasattr = 0; #endif // Is the file a directory? #if defined(WIN32) if (context->fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { #else if (context->dp->d_type == DT_DIR) { #endif // Knock out "." or ".." int ignore = filename[0] == '.' && (filename[1] == 0 || (filename[1] == '.' && filename[2] == 0)); // Should this file be ignored? int matches = 0; if (!ignore) { size_t len = strlen(filename); filename[len] = '/'; filename[len + 1] = '\0'; matches = fileglob_WildMatch(buffer_ptr(&context->matchPattern), filename, 0); } // Do a wildcard match. if (!ignore && matches) { // It matched. Let's see if the file should be ignored. // See if this is a directory to ignore. ignore = _fileglob_MatchIgnoreDirectoryPattern(self, filename); // Should this file be ignored? if (!ignore) { _fileglob_list_append(self, &context->directoryListHead, &context->directoryListTail, filename); // Is this pattern exclusive? if (self->exclusiveDirectoryPatternsHead) { if (_fileglob_MatchExclusiveDirectoryPattern(self, filename)) break; } else { if ((!context->matchFiles && context->pattern[0] == '/' && context->pattern[1] == 0) || (self->filesAndFolders)) break; } } } } else { // Do a wildcard match. if (fileglob_WildMatch(buffer_ptr(&context->matchPattern), filename, 0)) { // It matched. Let's see if the file should be ignored. int ignore = _fileglob_MatchIgnoreFilePattern(self, filename); // Is this pattern exclusive? if (!ignore && self->exclusiveFilePatternsHead) { ignore = !_fileglob_MatchExclusiveFilePattern(self, filename); } // Should this file be ignored? if (!ignore) { if (context->matchFiles) break; } } } NextFile: // Look up the next file. #if defined(WIN32) found = FindNextFile(context->handle, &context->fd) == TRUE; #else if (context->dirp) { context->dp = readdir(context->dirp); found = context->dp != NULL; } else { found = 0; } #endif if (!found) break; } if (!found) { // Close down the file find handle. #if defined(WIN32) FindClose(context->handle); context->handle = INVALID_HANDLE_VALUE; #else if (context->dirp) { closedir(context->dirp); context->dirp = NULL; } #endif context->iterNode = context->directoryListHead; } } // Iterate the file list and either recurse or add the file as a found // file. if (!context->matchFiles) { if (found) { return 1; } NextDirectory: if (context->iterNode) { // Need more directories. SplicePath(&self->combinedName, buffer_ptr(&context->basePath), context->iterNode->buffer); buffer_deltapos(&self->combinedName, -2); buffer_addstring(&self->combinedName, context->pattern, strlen(context->pattern) + 1); context->iterNode = context->iterNode->next; context = NULL; inPattern = buffer_ptr(&self->combinedName); goto Setup; } } else { if (found) return 1; } // Do we need to recurse? if (context->recurseAtPos == (size_t)-1) { _fileglob_FreeContextLevel(self); context = self->context; if (!context) return 0; goto NextDirectory; } buffer_reset(&context->matchPattern); buffer_setpos(&context->patternBuf, context->recurseAtPos); buffer_addstring(&context->matchPattern, buffer_posptr(&context->patternBuf), strlen(buffer_posptr(&context->patternBuf))); buffer_addstring(&context->patternBuf, "*/**/", 5); buffer_addstring(&context->patternBuf, buffer_ptr(&context->matchPattern), buffer_pos(&context->matchPattern) + 1); inPattern = buffer_ptr(&context->patternBuf); context->pattern = NULL; if (context->matchFiles) { context->iterNode = context->directoryListHead; } else { _fileglob_list_clear(self, &context->directoryListHead, &context->directoryListTail); } goto DoRecursion; }
static INT64_T chirp_fs_confuga_close (int fd) { int rc; SETUP_FILE switch (open_files[fd].type) { case CHIRP_FS_CONFUGA_REPL_READ: CATCH_CONFUGA(confuga_replica_close(open_files[fd].f.replica, STOPTIME)); break; case CHIRP_FS_CONFUGA_FILE_WRITE: { confuga_fid_t fid; confuga_off_t size; CATCH_CONFUGA(confuga_file_close(open_files[fd].f.file.file, &fid, &size, STOPTIME)); assert(open_files[fd].f.file.size == size); CATCH_CONFUGA(confuga_update(C, open_files[fd].path, fid, size, open_files[fd].f.file.flags)); break; } case CHIRP_FS_CONFUGA_META_READ: buffer_free(&open_files[fd].f.metadata); break; case CHIRP_FS_CONFUGA_META_WRITE: CATCH_CONFUGA(confuga_metadata_update(C, open_files[fd].path, buffer_tostring(&open_files[fd].f.metadata), buffer_pos(&open_files[fd].f.metadata))); buffer_free(&open_files[fd].f.metadata); break; default: assert(0); } open_files[fd].type = CHIRP_FS_CONFUGA_CLOSED; PROLOGUE }