📄 pvfs_shortname.c
字号:
} else { extension[0] = 0; } if (extension[0]) { return talloc_asprintf(mem_ctx, "%s.%s", prefix, extension); } return talloc_strdup(mem_ctx, prefix);}/* look for a DOS reserved name*/static bool is_reserved_name(struct pvfs_mangle_context *ctx, const char *name){ if (FLAG_CHECK(name[0], FLAG_POSSIBLE1) && FLAG_CHECK(name[1], FLAG_POSSIBLE2) && FLAG_CHECK(name[2], FLAG_POSSIBLE3) && FLAG_CHECK(name[3], FLAG_POSSIBLE4)) { /* a likely match, scan the lot */ int i; for (i=0; reserved_names[i]; i++) { if (strcasecmp(name, reserved_names[i]) == 0) { return true; } } } return false;}/* See if a filename is a legal long filename. A filename ending in a '.' is not legal unless it's "." or "..". JRA.*/static bool is_legal_name(struct pvfs_mangle_context *ctx, const char *name){ while (*name) { size_t c_size; codepoint_t c = next_codepoint(ctx->iconv_convenience, name, &c_size); if (c == INVALID_CODEPOINT) { return false; } /* all high chars are OK */ if (c >= 128) { name += c_size; continue; } if (FLAG_CHECK(c, FLAG_ILLEGAL)) { return false; } name += c_size; } return true;}/* the main forward mapping function, which converts a long filename to a 8.3 name if need83 is not set then we only do the mangling if the name is illegal as a long name if cache83 is not set then we don't cache the result return NULL if we don't need to do any conversion*/static char *name_map(struct pvfs_mangle_context *ctx, const char *name, bool need83, bool cache83){ char *dot_p; char lead_chars[7]; char extension[4]; unsigned int extension_length, i; unsigned int prefix_len; uint32_t hash, v; char *new_name; const char *basechars = MANGLE_BASECHARS; /* reserved names are handled specially */ if (!is_reserved_name(ctx, name)) { /* if the name is already a valid 8.3 name then we don't need to do anything */ if (is_8_3(ctx, name, false, false)) { return NULL; } /* if the caller doesn't strictly need 8.3 then just check for illegal filenames */ if (!need83 && is_legal_name(ctx, name)) { return NULL; } } /* find the '.' if any */ dot_p = strrchr(name, '.'); if (dot_p) { /* if the extension contains any illegal characters or is too long or zero length then we treat it as part of the prefix */ for (i=0; i<4 && dot_p[i+1]; i++) { if (! FLAG_CHECK(dot_p[i+1], FLAG_ASCII)) { dot_p = NULL; break; } } if (i == 0 || i == 4) dot_p = NULL; } /* the leading characters in the mangled name is taken from the first characters of the name, if they are ascii otherwise '_' is used */ for (i=0;i<ctx->mangle_prefix && name[i];i++) { lead_chars[i] = name[i]; if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) { lead_chars[i] = '_'; } lead_chars[i] = toupper((unsigned char)lead_chars[i]); } for (;i<ctx->mangle_prefix;i++) { lead_chars[i] = '_'; } /* the prefix is anything up to the first dot */ if (dot_p) { prefix_len = PTR_DIFF(dot_p, name); } else { prefix_len = strlen(name); } /* the extension of the mangled name is taken from the first 3 ascii chars after the dot */ extension_length = 0; if (dot_p) { for (i=1; extension_length < 3 && dot_p[i]; i++) { unsigned char c = dot_p[i]; if (FLAG_CHECK(c, FLAG_ASCII)) { extension[extension_length++] = toupper(c); } } } /* find the hash for this prefix */ v = hash = mangle_hash(ctx, name, prefix_len); new_name = talloc_array(ctx, char, 13); if (new_name == NULL) { return NULL; } /* now form the mangled name. */ for (i=0;i<ctx->mangle_prefix;i++) { new_name[i] = lead_chars[i]; } new_name[7] = basechars[v % 36]; new_name[6] = '~'; for (i=5; i>=ctx->mangle_prefix; i--) { v = v / 36; new_name[i] = basechars[v % 36]; } /* add the extension */ if (extension_length) { new_name[8] = '.'; memcpy(&new_name[9], extension, extension_length); new_name[9+extension_length] = 0; } else { new_name[8] = 0; } if (cache83) { /* put it in the cache */ cache_insert(ctx, name, prefix_len, hash); } M_DEBUG(10,("name_map: %s -> %08X -> %s (cache=%d)\n", name, hash, new_name, cache83)); return new_name;}/* initialise the flags table we allow only a very restricted set of characters as 'ascii' in this mangling backend. This isn't a significant problem as modern clients use the 'long' filenames anyway, and those don't have these restrictions. */static void init_tables(struct pvfs_mangle_context *ctx){ const char *basechars = MANGLE_BASECHARS; int i; /* the list of reserved dos names - all of these are illegal */ ZERO_STRUCT(ctx->char_flags); for (i=1;i<128;i++) { if ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z')) { ctx->char_flags[i] |= (FLAG_ASCII | FLAG_BASECHAR); } if (strchr("_-$~", i)) { ctx->char_flags[i] |= FLAG_ASCII; } if (strchr("*\\/?<>|\":", i)) { ctx->char_flags[i] |= FLAG_ILLEGAL; } if (strchr("*?\"<>", i)) { ctx->char_flags[i] |= FLAG_WILDCARD; } } ZERO_STRUCT(ctx->base_reverse); for (i=0;i<36;i++) { ctx->base_reverse[(uint8_t)basechars[i]] = i; } /* fill in the reserved names flags. These are used as a very fast filter for finding possible DOS reserved filenames */ for (i=0; reserved_names[i]; i++) { unsigned char c1, c2, c3, c4; c1 = (unsigned char)reserved_names[i][0]; c2 = (unsigned char)reserved_names[i][1]; c3 = (unsigned char)reserved_names[i][2]; c4 = (unsigned char)reserved_names[i][3]; ctx->char_flags[c1] |= FLAG_POSSIBLE1; ctx->char_flags[c2] |= FLAG_POSSIBLE2; ctx->char_flags[c3] |= FLAG_POSSIBLE3; ctx->char_flags[c4] |= FLAG_POSSIBLE4; ctx->char_flags[tolower(c1)] |= FLAG_POSSIBLE1; ctx->char_flags[tolower(c2)] |= FLAG_POSSIBLE2; ctx->char_flags[tolower(c3)] |= FLAG_POSSIBLE3; ctx->char_flags[tolower(c4)] |= FLAG_POSSIBLE4; ctx->char_flags[(unsigned char)'.'] |= FLAG_POSSIBLE4; } ctx->mangle_modulus = 1; for (i=0;i<(7-ctx->mangle_prefix);i++) { ctx->mangle_modulus *= 36; }}/* initialise the mangling code */NTSTATUS pvfs_mangle_init(struct pvfs_state *pvfs){ struct pvfs_mangle_context *ctx; ctx = talloc(pvfs, struct pvfs_mangle_context); if (ctx == NULL) { return NT_STATUS_NO_MEMORY; } ctx->iconv_convenience = lp_iconv_convenience(pvfs->ntvfs->ctx->lp_ctx); /* by default have a max of 512 entries in the cache. */ ctx->cache_size = lp_parm_int(pvfs->ntvfs->ctx->lp_ctx, NULL, "mangle", "cachesize", 512); ctx->prefix_cache = talloc_array(ctx, char *, ctx->cache_size); if (ctx->prefix_cache == NULL) { return NT_STATUS_NO_MEMORY; } ctx->prefix_cache_hashes = talloc_array(ctx, uint32_t, ctx->cache_size); if (ctx->prefix_cache_hashes == NULL) { return NT_STATUS_NO_MEMORY; } memset(ctx->prefix_cache, 0, sizeof(char *) * ctx->cache_size); memset(ctx->prefix_cache_hashes, 0, sizeof(uint32_t) * ctx->cache_size); ctx->mangle_prefix = lp_parm_int(pvfs->ntvfs->ctx->lp_ctx, NULL, "mangle", "prefix", -1); if (ctx->mangle_prefix < 0 || ctx->mangle_prefix > 6) { ctx->mangle_prefix = DEFAULT_MANGLE_PREFIX; } init_tables(ctx); pvfs->mangle_ctx = ctx; return NT_STATUS_OK;}/* return the short name for a component of a full name*/char *pvfs_short_name_component(struct pvfs_state *pvfs, const char *name){ return name_map(pvfs->mangle_ctx, name, true, true);}/* return the short name for a given entry in a directory*/const char *pvfs_short_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, struct pvfs_filename *name){ char *p = strrchr(name->full_name, '/'); char *ret = pvfs_short_name_component(pvfs, p+1); if (ret == NULL) { return p+1; } talloc_steal(mem_ctx, ret); return ret;}/* lookup a mangled name, returning the original long name if present in the cache*/char *pvfs_mangled_lookup(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, const char *name){ return check_cache(pvfs->mangle_ctx, mem_ctx, name);}/* look for a DOS reserved name*/bool pvfs_is_reserved_name(struct pvfs_state *pvfs, const char *name){ return is_reserved_name(pvfs->mangle_ctx, name);}/* see if a component of a filename could be a mangled name from our mangling code*/bool pvfs_is_mangled_component(struct pvfs_state *pvfs, const char *name){ return is_mangled_component(pvfs->mangle_ctx, name, strlen(name));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -