X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Flib%2Futil.c;h=bab399824bf811f34fba93ac75c2f6d71e5d0068;hb=631e063f6bb49da426ca7343b6987f7831078d7f;hp=5ca2a7f93133cedd29fac93a625ecd2f8f5172dc;hpb=0b5e354080ae1990b1f8acc470bfbad3f92868b8;p=vlendec%2Fsamba-autobuild%2F.git diff --git a/source3/lib/util.c b/source3/lib/util.c index 5ca2a7f9313..bab399824bf 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -28,9 +28,12 @@ #include "ctdbd_conn.h" #include "../lib/util/util_pw.h" #include "messages.h" -#include +#include "messages_dgm.h" #include "libcli/security/security.h" #include "serverid.h" +#include "lib/util/sys_rw.h" +#include "lib/util/sys_rw_data.h" +#include "lib/util/util_process.h" #ifdef HAVE_SYS_PRCTL_H #include @@ -197,7 +200,7 @@ void show_msg(const char *buf) if (DEBUGLEVEL < 50) bcc = MIN(bcc, 512); - dump_data(10, (const uint8 *)smb_buf_const(buf), bcc); + dump_data(10, (const uint8_t *)smb_buf_const(buf), bcc); } /******************************************************************* @@ -217,12 +220,12 @@ int set_message_bcc(char *buf,int num_bytes) Return the bytes added ********************************************************************/ -ssize_t message_push_blob(uint8 **outbuf, DATA_BLOB blob) +ssize_t message_push_blob(uint8_t **outbuf, DATA_BLOB blob) { size_t newlen = smb_len(*outbuf) + 4 + blob.length; - uint8 *tmp; + uint8_t *tmp; - if (!(tmp = talloc_realloc(NULL, *outbuf, uint8, newlen))) { + if (!(tmp = talloc_realloc(NULL, *outbuf, uint8_t, newlen))) { DEBUG(0, ("talloc failed\n")); return -1; } @@ -428,8 +431,9 @@ static void reinit_after_fork_pipe_handler(struct tevent_context *ev, NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, - struct event_context *ev_ctx, - bool parent_longlived) + struct tevent_context *ev_ctx, + bool parent_longlived, + const char *comment) { NTSTATUS status = NT_STATUS_OK; @@ -438,12 +442,6 @@ NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, reinit_after_fork_pipe[1] = -1; } - /* Reset the state of the random - * number generation system, so - * children do not get the same random - * numbers as each other */ - set_need_random_reseed(); - /* tdb needs special fork handling */ if (tdb_reopen_all(parent_longlived ? 1 : 0) != 0) { DEBUG(0,("tdb_reopen_all failed.\n")); @@ -451,8 +449,11 @@ NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, goto done; } - if (ev_ctx && tevent_re_initialise(ev_ctx) != 0) { - smb_panic(__location__ ": Failed to re-initialise event context"); + if (ev_ctx != NULL) { + tevent_set_trace_callback(ev_ctx, NULL, NULL); + if (tevent_re_initialise(ev_ctx) != 0) { + smb_panic(__location__ ": Failed to re-initialise event context"); + } } if (reinit_after_fork_pipe[0] != -1) { @@ -477,6 +478,11 @@ NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, nt_errstr(status))); } } + + if (comment) { + prctl_set_comment(comment); + } + done: return status; } @@ -486,7 +492,7 @@ NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, ****************************************************************************/ void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size, - void *element, void *_array, uint32 *num_elements, + void *element, void *_array, uint32_t *num_elements, ssize_t *array_size) { void **array = (void **)_array; @@ -559,31 +565,6 @@ char *get_mydnsdomname(TALLOC_CTX *ctx) } } -/**************************************************************************** - Interpret a protocol description string, with a default. -****************************************************************************/ - -int interpret_protocol(const char *str,int def) -{ - if (strequal(str,"NT1")) - return(PROTOCOL_NT1); - if (strequal(str,"LANMAN2")) - return(PROTOCOL_LANMAN2); - if (strequal(str,"LANMAN1")) - return(PROTOCOL_LANMAN1); - if (strequal(str,"CORE")) - return(PROTOCOL_CORE); - if (strequal(str,"COREPLUS")) - return(PROTOCOL_COREPLUS); - if (strequal(str,"CORE+")) - return(PROTOCOL_COREPLUS); - - DEBUG(0,("Unrecognised protocol level %s\n",str)); - - return(def); -} - - #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT)) /****************************************************************** Remove any mount options such as -rsize=2048,wsize=2048 etc. @@ -618,7 +599,7 @@ char *automount_lookup(TALLOC_CTX *ctx, const char *user_name) { char *value = NULL; - char *nis_map = (char *)lp_nis_home_map_name(); + char *nis_map = (char *)lp_homedir_map(); char buffer[NIS_MAXATTRVAL + 1]; nis_result *result; @@ -670,7 +651,7 @@ char *automount_lookup(TALLOC_CTX *ctx, const char *user_name) char *nis_result; /* yp_match inits this */ int nis_result_len; /* and set this */ char *nis_domain; /* yp_get_default_domain inits this */ - char *nis_map = lp_nis_home_map_name(talloc_tos()); + char *nis_map = lp_homedir_map(talloc_tos()); if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) { DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); @@ -707,81 +688,11 @@ char *automount_lookup(TALLOC_CTX *ctx, const char *user_name) #endif /* WITH_NISPLUS_HOME */ #endif -/**************************************************************************** - Check if a process exists. Does this work on all unixes? -****************************************************************************/ - bool process_exists(const struct server_id pid) { return serverid_exists(&pid); } -bool processes_exist(const struct server_id *pids, int num_pids, - bool *results) -{ - struct server_id *remote_pids = NULL; - int *remote_idx = NULL; - bool *remote_results = NULL; - int i, num_remote_pids; - bool result = false; - - remote_pids = talloc_array(talloc_tos(), struct server_id, num_pids); - if (remote_pids == NULL) { - goto fail; - } - remote_idx = talloc_array(talloc_tos(), int, num_pids); - if (remote_idx == NULL) { - goto fail; - } - remote_results = talloc_array(talloc_tos(), bool, num_pids); - if (remote_results == NULL) { - goto fail; - } - - num_remote_pids = 0; - - for (i=0; i= ARRAY_SIZE(remote_arch_strings)) { + /* + * set_remote_arch() already checks this so ra_type + * should be in the allowed range, but anyway, let's + * do another bound check here. + */ + DBG_ERR("Remote arch info out of sync [%d] missing\n", ra_type); + ra_type = RA_UNKNOWN; + } + return remote_arch_strings[ra_type]; +} + +enum remote_arch_types get_remote_arch_from_str(const char *remote_arch_string) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(remote_arch_strings); i++) { + if (strcmp(remote_arch_string, remote_arch_strings[i]) == 0) { + return i; + } } - return remote_arch_str; + return RA_UNKNOWN; } /******************************************************************* @@ -1324,52 +1309,20 @@ const char *get_remote_arch_str(void) void set_remote_arch(enum remote_arch_types type) { - ra_type = type; - switch( type ) { - case RA_WFWG: - remote_arch_str = "WfWg"; - break; - case RA_OS2: - remote_arch_str = "OS2"; - break; - case RA_WIN95: - remote_arch_str = "Win95"; - break; - case RA_WINNT: - remote_arch_str = "WinNT"; - break; - case RA_WIN2K: - remote_arch_str = "Win2K"; - break; - case RA_WINXP: - remote_arch_str = "WinXP"; - break; - case RA_WINXP64: - remote_arch_str = "WinXP64"; - break; - case RA_WIN2K3: - remote_arch_str = "Win2K3"; - break; - case RA_VISTA: - remote_arch_str = "Vista"; - break; - case RA_SAMBA: - remote_arch_str = "Samba"; - break; - case RA_CIFSFS: - remote_arch_str = "CIFSFS"; - break; - case RA_OSX: - remote_arch_str = "OSX"; - break; - default: + if (ra_type >= ARRAY_SIZE(remote_arch_strings)) { + /* + * This protects against someone adding values to enum + * remote_arch_types without updating + * remote_arch_strings array. + */ + DBG_ERR("Remote arch info out of sync [%d] missing\n", ra_type); ra_type = RA_UNKNOWN; - remote_arch_str = "UNKNOWN"; - break; + return; } + ra_type = type; DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n", - remote_arch_str)); + get_remote_arch_str())); } /******************************************************************* @@ -1381,6 +1334,146 @@ enum remote_arch_types get_remote_arch(void) return ra_type; } +#define RA_CACHE_TTL 7*24*3600 + +static bool remote_arch_cache_key(const struct GUID *client_guid, + fstring key) +{ + struct GUID_txt_buf guid_buf; + const char *guid_string = NULL; + + guid_string = GUID_buf_string(client_guid, &guid_buf); + if (guid_string == NULL) { + return false; + } + + fstr_sprintf(key, "RA/%s", guid_string); + return true; +} + +struct ra_parser_state { + bool found; + enum remote_arch_types ra; +}; + +static void ra_parser(time_t timeout, DATA_BLOB blob, void *priv_data) +{ + struct ra_parser_state *state = (struct ra_parser_state *)priv_data; + const char *ra_str = NULL; + + if (timeout <= time(NULL)) { + return; + } + + if ((blob.length == 0) || (blob.data[blob.length-1] != '\0')) { + DBG_ERR("Remote arch cache key not a string\n"); + return; + } + + ra_str = (const char *)blob.data; + DBG_INFO("Got remote arch [%s] from cache\n", ra_str); + + state->ra = get_remote_arch_from_str(ra_str); + state->found = true; + return; +} + +static bool remote_arch_cache_get(const struct GUID *client_guid) +{ + bool ok; + fstring ra_key; + struct ra_parser_state state = (struct ra_parser_state) { + .found = false, + .ra = RA_UNKNOWN, + }; + + ok = remote_arch_cache_key(client_guid, ra_key); + if (!ok) { + return false; + } + + ok = gencache_parse(ra_key, ra_parser, &state); + if (!ok || !state.found) { + return true; + } + + if (state.ra == RA_UNKNOWN) { + return true; + } + + set_remote_arch(state.ra); + return true; +} + +static bool remote_arch_cache_set(const struct GUID *client_guid) +{ + bool ok; + fstring ra_key; + const char *ra_str = NULL; + + if (get_remote_arch() == RA_UNKNOWN) { + return true; + } + + ok = remote_arch_cache_key(client_guid, ra_key); + if (!ok) { + return false; + } + + ra_str = get_remote_arch_str(); + if (ra_str == NULL) { + return false; + } + + ok = gencache_set(ra_key, ra_str, time(NULL) + RA_CACHE_TTL); + if (!ok) { + return false; + } + + return true; +} + +bool remote_arch_cache_update(const struct GUID *client_guid) +{ + bool ok; + + if (get_remote_arch() == RA_UNKNOWN) { + + become_root(); + ok = remote_arch_cache_get(client_guid); + unbecome_root(); + + return ok; + } + + become_root(); + ok = remote_arch_cache_set(client_guid); + unbecome_root(); + + return ok; +} + +bool remote_arch_cache_delete(const struct GUID *client_guid) +{ + bool ok; + fstring ra_key; + + ok = remote_arch_cache_key(client_guid, ra_key); + if (!ok) { + return false; + } + + become_root(); + ok = gencache_del(ra_key); + unbecome_root(); + + if (!ok) { + return false; + } + + return true; +} + const char *tab_depth(int level, int depth) { if( CHECK_DEBUGLVL(level) ) { @@ -1400,9 +1493,14 @@ const char *tab_depth(int level, int depth) int str_checksum(const char *s) { + TDB_DATA key; if (s == NULL) return 0; - return hash(s, strlen(s), 0); + + key = (TDB_DATA) { .dptr = discard_const_p(uint8_t, s), + .dsize = strlen(s) }; + + return tdb_jenkins_hash(&key); } /***************************************************************** @@ -1557,86 +1655,18 @@ char *myhostname(void) char *myhostname_upper(void) { - char *name; static char *ret; if (ret == NULL) { - name = get_myname(talloc_tos()); + char *name = get_myname(NULL); + if (name == NULL) { + return NULL; + } ret = strupper_talloc(NULL, name); talloc_free(name); } return ret; } -/** - * @brief Returns an absolute path to a file concatenating the provided - * @a rootpath and @a basename - * - * @param name Filename, relative to @a rootpath - * - * @retval Pointer to a string containing the full path. - **/ - -static char *xx_path(const char *name, const char *rootpath) -{ - char *fname = NULL; - - fname = talloc_strdup(talloc_tos(), rootpath); - if (!fname) { - return NULL; - } - trim_string(fname,"","/"); - - if (!directory_exist(fname)) { - if (!mkdir(fname,0755)) - DEBUG(1, ("Unable to create directory %s for file %s. " - "Error was %s\n", fname, name, strerror(errno))); - } - - return talloc_asprintf(talloc_tos(), - "%s/%s", - fname, - name); -} - -/** - * @brief Returns an absolute path to a file in the Samba lock directory. - * - * @param name File to find, relative to LOCKDIR. - * - * @retval Pointer to a talloc'ed string containing the full path. - **/ - -char *lock_path(const char *name) -{ - return xx_path(name, lp_lockdir()); -} - -/** - * @brief Returns an absolute path to a file in the Samba state directory. - * - * @param name File to find, relative to STATEDIR. - * - * @retval Pointer to a talloc'ed string containing the full path. - **/ - -char *state_path(const char *name) -{ - return xx_path(name, lp_statedir()); -} - -/** - * @brief Returns an absolute path to a file in the Samba cache directory. - * - * @param name File to find, relative to CACHEDIR. - * - * @retval Pointer to a talloc'ed string containing the full path. - **/ - -char *cache_path(const char *name) -{ - return xx_path(name, lp_cachedir()); -} - /******************************************************************* Given a filename - get its directory name ********************************************************************/ @@ -1680,11 +1710,6 @@ bool ms_has_wild(const char *s) { char c; - if (lp_posix_pathnames()) { - /* With posix pathnames no characters are wild. */ - return False; - } - while ((c = *s++)) { switch (c) { case '*': @@ -1907,78 +1932,64 @@ bool unix_wild_match(const char *pattern, const char *string) } /********************************************************************** - Converts a name to a fully qualified domain name. - Returns true if lookup succeeded, false if not (then fqdn is set to name) - Note we deliberately use gethostbyname here, not getaddrinfo as we want - to examine the h_aliases and I don't know how to do that with getaddrinfo. -***********************************************************************/ + Converts a name to a fully qualified domain name. + Returns true if lookup succeeded, false if not (then fqdn is set to name) + Uses getaddrinfo() with AI_CANONNAME flag to obtain the official + canonical name of the host. getaddrinfo() may use a variety of sources + including /etc/hosts to obtain the domainname. It expects aliases in + /etc/hosts to NOT be the FQDN. The FQDN should come first. +************************************************************************/ bool name_to_fqdn(fstring fqdn, const char *name) { char *full = NULL; - struct hostent *hp = gethostbyname(name); + struct addrinfo hints; + struct addrinfo *result; + int s; + + /* Configure hints to obtain canonical name */ - if (!hp || !hp->h_name || !*hp->h_name) { + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ + hints.ai_flags = AI_CANONNAME; /* Get host's FQDN */ + hints.ai_protocol = 0; /* Any protocol */ + + s = getaddrinfo(name, NULL, &hints, &result); + if (s != 0) { + DEBUG(1, ("getaddrinfo: %s\n", gai_strerror(s))); DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name)); fstrcpy(fqdn, name); return false; } + full = result->ai_canonname; - /* Find out if the fqdn is returned as an alias + /* Find out if the FQDN is returned as an alias * to cope with /etc/hosts files where the first - * name is not the fqdn but the short name */ - if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) { - int i; - for (i = 0; hp->h_aliases[i]; i++) { - if (strchr_m(hp->h_aliases[i], '.')) { - full = hp->h_aliases[i]; - break; - } - } + * name is not the FQDN but the short name. + * getaddrinfo provides no easy way of handling aliases + * in /etc/hosts. Users should make sure the FQDN + * comes first in /etc/hosts. */ + if (full && (! strchr_m(full, '.'))) { + DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n")); + DEBUGADD(1, (" Full qualified domain names (FQDNs) should not be specified\n")); + DEBUGADD(1, (" as an alias in /etc/hosts. FQDN should be the first name\n")); + DEBUGADD(1, (" prior to any aliases.\n")); } if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) { DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n")); - DEBUGADD(1, (" Specifing the machine hostname for address 127.0.0.1 may lead\n")); + DEBUGADD(1, (" Specifying the machine hostname for address 127.0.0.1 may lead\n")); DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n")); DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n")); - full = hp->h_name; - } - if (!full) { - full = hp->h_name; } DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full)); fstrcpy(fqdn, full); + freeaddrinfo(result); /* No longer needed */ return true; } -/********************************************************************** - Append a DATA_BLOB to a talloc'ed object -***********************************************************************/ - -void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob) -{ - size_t old_size = 0; - char *result; - - if (blob.length == 0) { - return buf; - } - - if (buf != NULL) { - old_size = talloc_get_size(buf); - } - - result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length); - if (result == NULL) { - return NULL; - } - - memcpy(result + old_size, blob.data, blob.length); - return result; -} - -uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options) +uint32_t map_share_mode_to_deny_mode(uint32_t share_access, uint32_t private_options) { switch (share_access & ~FILE_SHARE_DELETE) { case FILE_SHARE_NONE: @@ -1996,100 +2007,7 @@ uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options) return DENY_FCB; } - return (uint32)-1; -} - -pid_t procid_to_pid(const struct server_id *proc) -{ - return proc->pid; -} - -static uint32 my_vnn = NONCLUSTER_VNN; - -void set_my_vnn(uint32 vnn) -{ - DEBUG(10, ("vnn pid %d = %u\n", (int)getpid(), (unsigned int)vnn)); - my_vnn = vnn; -} - -uint32 get_my_vnn(void) -{ - return my_vnn; -} - -static uint64_t my_unique_id = 0; - -void set_my_unique_id(uint64_t unique_id) -{ - my_unique_id = unique_id; -} - -struct server_id pid_to_procid(pid_t pid) -{ - struct server_id result; - result.pid = pid; - result.task_id = 0; - result.unique_id = my_unique_id; - result.vnn = my_vnn; - return result; -} - -struct server_id procid_self(void) -{ - return pid_to_procid(getpid()); -} - -static struct idr_context *task_id_tree; - -static int free_task_id(struct server_id *server_id) -{ - idr_remove(task_id_tree, server_id->task_id); - return 0; -} - -/* Return a server_id with a unique task_id element. Free the - * returned pointer to de-allocate the task_id via a talloc destructor - * (ie, use talloc_free()) */ -struct server_id *new_server_id_task(TALLOC_CTX *mem_ctx) -{ - struct server_id *server_id; - int task_id; - if (!task_id_tree) { - task_id_tree = idr_init(NULL); - if (!task_id_tree) { - return NULL; - } - } - - server_id = talloc(mem_ctx, struct server_id); - - if (!server_id) { - return NULL; - } - *server_id = procid_self(); - - /* 0 is the default server_id, so we need to start with 1 */ - task_id = idr_get_new_above(task_id_tree, server_id, 1, INT32_MAX); - - if (task_id == -1) { - talloc_free(server_id); - return NULL; - } - - talloc_set_destructor(server_id, free_task_id); - server_id->task_id = task_id; - return server_id; -} - -bool procid_is_me(const struct server_id *pid) -{ - if (pid->pid != getpid()) - return False; - if (pid->task_id != 0) - return False; - if (pid->vnn != my_vnn) - return False; - return True; + return (uint32_t)-1; } struct server_id interpret_pid(const char *pid_string) @@ -2097,21 +2015,6 @@ struct server_id interpret_pid(const char *pid_string) return server_id_from_string(get_my_vnn(), pid_string); } -char *procid_str_static(const struct server_id *pid) -{ - return server_id_str(talloc_tos(), pid); -} - -bool procid_valid(const struct server_id *pid) -{ - return (pid->pid != (uint64_t)-1); -} - -bool procid_is_local(const struct server_id *pid) -{ - return pid->vnn == my_vnn; -} - /**************************************************************** Check if an offset into a buffer is safe. If this returns True it's safe to indirect into the byte at @@ -2200,7 +2103,7 @@ int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, i call (they take care of winbind separator and other winbind specific settings). ****************************************************************/ -void split_domain_user(TALLOC_CTX *mem_ctx, +bool split_domain_user(TALLOC_CTX *mem_ctx, const char *full_name, char **domain, char **user) @@ -2212,11 +2115,23 @@ void split_domain_user(TALLOC_CTX *mem_ctx, if (p != NULL) { *domain = talloc_strndup(mem_ctx, full_name, PTR_DIFF(p, full_name)); + if (*domain == NULL) { + return false; + } *user = talloc_strdup(mem_ctx, p+1); + if (*user == NULL) { + TALLOC_FREE(*domain); + return false; + } } else { - *domain = talloc_strdup(mem_ctx, ""); + *domain = NULL; *user = talloc_strdup(mem_ctx, full_name); + if (*user == NULL) { + return false; + } } + + return true; } /**************************************************************** @@ -2314,16 +2229,16 @@ bool is_executable(const char *fname) bool map_open_params_to_ntcreate(const char *smb_base_fname, int deny_mode, int open_func, - uint32 *paccess_mask, - uint32 *pshare_mode, - uint32 *pcreate_disposition, - uint32 *pcreate_options, + uint32_t *paccess_mask, + uint32_t *pshare_mode, + uint32_t *pcreate_disposition, + uint32_t *pcreate_options, uint32_t *pprivate_flags) { - uint32 access_mask; - uint32 share_mode; - uint32 create_disposition; - uint32 create_options = FILE_NON_DIRECTORY_FILE; + uint32_t access_mask; + uint32_t share_mode; + uint32_t create_disposition; + uint32_t create_options = FILE_NON_DIRECTORY_FILE; uint32_t private_flags = 0; DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, " @@ -2484,3 +2399,45 @@ struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct securi } return cpy; } + +/**************************************************************************** + Check that a file matches a particular file type. +****************************************************************************/ + +bool dir_check_ftype(uint32_t mode, uint32_t dirtype) +{ + uint32_t mask; + + /* Check the "may have" search bits. */ + if (((mode & ~dirtype) & + (FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_SYSTEM | + FILE_ATTRIBUTE_DIRECTORY)) != 0) { + return false; + } + + /* Check the "must have" bits, + which are the may have bits shifted eight */ + /* If must have bit is set, the file/dir can + not be returned in search unless the matching + file attribute is set */ + mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY| + FILE_ATTRIBUTE_ARCHIVE| + FILE_ATTRIBUTE_READONLY| + FILE_ATTRIBUTE_HIDDEN| + FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */ + if(mask) { + if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY| + FILE_ATTRIBUTE_ARCHIVE| + FILE_ATTRIBUTE_READONLY| + FILE_ATTRIBUTE_HIDDEN| + FILE_ATTRIBUTE_SYSTEM))) == mask) { + /* check if matching attribute present */ + return true; + } else { + return false; + } + } + + return true; +}