関数 | |
static BOOL | scan_directory (connection_struct *conn, const char *path, char *name, size_t maxlength) |
static BOOL | fname_equal (const char *name1, const char *name2, BOOL case_sensitive) |
static BOOL | mangled_equal (const char *name1, const char *name2, const struct share_params *p) |
static NTSTATUS | determine_path_error (const char *name, BOOL allow_wcard_last_component) |
NTSTATUS | unix_convert (connection_struct *conn, pstring name, BOOL allow_wcard_last_component, char *saved_last_component, SMB_STRUCT_STAT *pst) |
NTSTATUS | check_name (connection_struct *conn, const pstring name) |
static BOOL scan_directory | ( | connection_struct * | conn, | |
const char * | path, | |||
char * | name, | |||
size_t | maxlength | |||
) | [static] |
filename.c の 552 行で定義されています。
参照先 connection_struct::case_sensitive・CloseDir()・smb_Dir::conn・cur_dir・errno・fname_equal()・mangle_check_cache()・mangle_is_mangled()・mangled_equal()・OpenDir()・connection_struct::params・ReadDirName().
参照元 unix_convert().
00553 { 00554 struct smb_Dir *cur_dir; 00555 const char *dname; 00556 BOOL mangled; 00557 long curpos; 00558 00559 mangled = mangle_is_mangled(name, conn->params); 00560 00561 /* handle null paths */ 00562 if (*path == 0) 00563 path = "."; 00564 00565 /* 00566 * The incoming name can be mangled, and if we de-mangle it 00567 * here it will not compare correctly against the filename (name2) 00568 * read from the directory and then mangled by the mangle_map() 00569 * call. We need to mangle both names or neither. 00570 * (JRA). 00571 * 00572 * Fix for bug found by Dina Fine. If in case sensitive mode then 00573 * the mangle cache is no good (3 letter extension could be wrong 00574 * case - so don't demangle in this case - leave as mangled and 00575 * allow the mangling of the directory entry read (which is done 00576 * case insensitively) to match instead. This will lead to more 00577 * false positive matches but we fail completely without it. JRA. 00578 */ 00579 00580 if (mangled && !conn->case_sensitive) { 00581 mangled = !mangle_check_cache( name, maxlength, conn->params); 00582 } 00583 00584 /* open the directory */ 00585 if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { 00586 DEBUG(3,("scan dir didn't open dir [%s]\n",path)); 00587 return(False); 00588 } 00589 00590 /* now scan for matching names */ 00591 curpos = 0; 00592 while ((dname = ReadDirName(cur_dir, &curpos))) { 00593 00594 /* Is it dot or dot dot. */ 00595 if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) { 00596 continue; 00597 } 00598 00599 /* 00600 * At this point dname is the unmangled name. 00601 * name is either mangled or not, depending on the state of the "mangled" 00602 * variable. JRA. 00603 */ 00604 00605 /* 00606 * Check mangled name against mangled name, or unmangled name 00607 * against unmangled name. 00608 */ 00609 00610 if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { 00611 /* we've found the file, change it's name and return */ 00612 safe_strcpy(name, dname, maxlength); 00613 CloseDir(cur_dir); 00614 return(True); 00615 } 00616 } 00617 00618 CloseDir(cur_dir); 00619 errno = ENOENT; 00620 return(False); 00621 }
filename.c の 36 行で定義されています。
参照先 strequal().
参照元 scan_directory().
00037 { 00038 /* Normal filename handling */ 00039 if (case_sensitive) 00040 return(strcmp(name1,name2) == 0); 00041 00042 return(strequal(name1,name2)); 00043 }
static BOOL mangled_equal | ( | const char * | name1, | |
const char * | name2, | |||
const struct share_params * | p | |||
) | [static] |
filename.c の 49 行で定義されています。
参照先 mangle_map()・strequal().
参照元 scan_directory().
00051 { 00052 pstring tmpname; 00053 00054 pstrcpy(tmpname, name2); 00055 mangle_map(tmpname, True, False, p); 00056 return strequal(name1, tmpname); 00057 }
static NTSTATUS determine_path_error | ( | const char * | name, | |
BOOL | allow_wcard_last_component | |||
) | [static] |
filename.c の 63 行で定義されています。
参照先 ms_has_wild().
参照元 unix_convert().
00064 { 00065 const char *p; 00066 00067 if (!allow_wcard_last_component) { 00068 /* Error code within a pathname. */ 00069 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 00070 } 00071 00072 /* We're terminating here so we 00073 * can be a little slower and get 00074 * the error code right. Windows 00075 * treats the last part of the pathname 00076 * separately I think, so if the last 00077 * component is a wildcard then we treat 00078 * this ./ as "end of component" */ 00079 00080 p = strchr(name, '/'); 00081 00082 if (!p && (ms_has_wild(name) || ISDOT(name))) { 00083 /* Error code at the end of a pathname. */ 00084 return NT_STATUS_OBJECT_NAME_INVALID; 00085 } else { 00086 /* Error code within a pathname. */ 00087 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 00088 } 00089 }
NTSTATUS unix_convert | ( | connection_struct * | conn, | |
pstring | name, | |||
BOOL | allow_wcard_last_component, | |||
char * | saved_last_component, | |||
SMB_STRUCT_STAT * | pst | |||
) |
filename.c の 120 行で定義されています。
参照先 connection_struct::case_preserve・connection_struct::case_sensitive・determine_path_error()・errno・get_delete_on_close_flag()・mangle_check_cache()・mangle_is_8_3()・mangle_is_mangled()・map_nt_error_from_unix()・ms_has_wild()・connection_struct::params・connection_struct::printer・scan_directory()・connection_struct::short_case_preserve・stat_cache_add()・stat_cache_lookup()・strnorm()・strrchr_m().
参照元 _srv_net_file_query_secdesc()・_srv_net_file_set_secdesc()・call_nt_transact_create()・call_trans2findfirst()・call_trans2mkdir()・call_trans2open()・call_trans2qfilepathinfo()・call_trans2setfilepathinfo()・copy_internals()・dfs_path_lookup()・driver_unix_convert()・hardlink_internals()・rename_internals()・rename_internals_fsp()・reply_checkpath()・reply_copy()・reply_ctemp()・reply_getatr()・reply_mkdir()・reply_mknew()・reply_ntcreate_and_X()・reply_open()・reply_open_and_X()・reply_rmdir()・reply_search()・reply_setatr()・unlink_internals().
00125 { 00126 SMB_STRUCT_STAT st; 00127 char *start, *end; 00128 pstring dirpath; 00129 pstring orig_path; 00130 BOOL component_was_mangled = False; 00131 BOOL name_has_wildcard = False; 00132 00133 SET_STAT_INVALID(*pst); 00134 00135 *dirpath = 0; 00136 00137 if(saved_last_component) { 00138 *saved_last_component = 0; 00139 } 00140 00141 if (conn->printer) { 00142 /* we don't ever use the filenames on a printer share as a 00143 filename - so don't convert them */ 00144 return NT_STATUS_OK; 00145 } 00146 00147 DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); 00148 00149 /* 00150 * Conversion to basic unix format is already done in check_path_syntax(). 00151 */ 00152 00153 /* 00154 * Names must be relative to the root of the service - any leading /. 00155 * and trailing /'s should have been trimmed by check_path_syntax(). 00156 */ 00157 00158 #ifdef DEVELOPER 00159 SMB_ASSERT(*name != '/'); 00160 #endif 00161 00162 /* 00163 * If we trimmed down to a single '\0' character 00164 * then we should use the "." directory to avoid 00165 * searching the cache, but not if we are in a 00166 * printing share. 00167 * As we know this is valid we can return true here. 00168 */ 00169 00170 if (!*name) { 00171 name[0] = '.'; 00172 name[1] = '\0'; 00173 if (SMB_VFS_STAT(conn,name,&st) == 0) { 00174 *pst = st; 00175 } 00176 DEBUG(5,("conversion finished \"\" -> %s\n",name)); 00177 return NT_STATUS_OK; 00178 } 00179 00180 if (name[0] == '.' && (name[1] == '/' || name[1] == '\0')) { 00181 /* Start of pathname can't be "." only. */ 00182 if (name[1] == '\0' || name[2] == '\0') { 00183 return NT_STATUS_OBJECT_NAME_INVALID; 00184 } else { 00185 return determine_path_error(&name[2], allow_wcard_last_component); 00186 } 00187 } 00188 00189 /* 00190 * Ensure saved_last_component is valid even if file exists. 00191 */ 00192 00193 if(saved_last_component) { 00194 end = strrchr_m(name, '/'); 00195 if (end) { 00196 pstrcpy(saved_last_component, end + 1); 00197 } else { 00198 pstrcpy(saved_last_component, name); 00199 } 00200 } 00201 00202 /* 00203 * Large directory fix normalization. If we're case sensitive, and 00204 * the case preserving parameters are set to "no", normalize the case of 00205 * the incoming filename from the client WHETHER IT EXISTS OR NOT ! 00206 * This is in conflict with the current (3.0.20) man page, but is 00207 * what people expect from the "large directory howto". I'll update 00208 * the man page. Thanks to jht@samba.org for finding this. JRA. 00209 */ 00210 00211 if (conn->case_sensitive && !conn->case_preserve && !conn->short_case_preserve) { 00212 strnorm(name, lp_defaultcase(SNUM(conn))); 00213 } 00214 00215 start = name; 00216 pstrcpy(orig_path, name); 00217 00218 if(!conn->case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { 00219 *pst = st; 00220 return NT_STATUS_OK; 00221 } 00222 00223 /* 00224 * stat the name - if it exists then we are all done! 00225 */ 00226 00227 if (SMB_VFS_STAT(conn,name,&st) == 0) { 00228 /* Ensure we catch all names with in "/." 00229 this is disallowed under Windows. */ 00230 const char *p = strstr(name, "/."); /* mb safe. */ 00231 if (p) { 00232 if (p[2] == '/') { 00233 /* Error code within a pathname. */ 00234 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 00235 } else if (p[2] == '\0') { 00236 /* Error code at the end of a pathname. */ 00237 return NT_STATUS_OBJECT_NAME_INVALID; 00238 } 00239 } 00240 stat_cache_add(orig_path, name, conn->case_sensitive); 00241 DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); 00242 *pst = st; 00243 return NT_STATUS_OK; 00244 } 00245 00246 DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start)); 00247 00248 /* 00249 * A special case - if we don't have any mangling chars and are case 00250 * sensitive then searching won't help. 00251 */ 00252 00253 if (conn->case_sensitive && 00254 !mangle_is_mangled(name, conn->params) && 00255 !*lp_mangled_map(conn->params)) { 00256 return NT_STATUS_OK; 00257 } 00258 00259 /* 00260 * is_mangled() was changed to look at an entire pathname, not 00261 * just a component. JRA. 00262 */ 00263 00264 if (mangle_is_mangled(start, conn->params)) { 00265 component_was_mangled = True; 00266 } 00267 00268 /* 00269 * Now we need to recursively match the name against the real 00270 * directory structure. 00271 */ 00272 00273 /* 00274 * Match each part of the path name separately, trying the names 00275 * as is first, then trying to scan the directory for matching names. 00276 */ 00277 00278 for (; start ; start = (end?end+1:(char *)NULL)) { 00279 /* 00280 * Pinpoint the end of this section of the filename. 00281 */ 00282 end = strchr(start, '/'); /* mb safe. '/' can't be in any encoded char. */ 00283 00284 /* 00285 * Chop the name at this point. 00286 */ 00287 if (end) { 00288 *end = 0; 00289 } 00290 00291 if (saved_last_component != 0) { 00292 pstrcpy(saved_last_component, end ? end + 1 : start); 00293 } 00294 00295 /* The name cannot have a component of "." */ 00296 00297 if (ISDOT(start)) { 00298 if (!end) { 00299 /* Error code at the end of a pathname. */ 00300 return NT_STATUS_OBJECT_NAME_INVALID; 00301 } 00302 return determine_path_error(end+1, allow_wcard_last_component); 00303 } 00304 00305 /* The name cannot have a wildcard if it's not 00306 the last component. */ 00307 00308 name_has_wildcard = ms_has_wild(start); 00309 00310 /* Wildcard not valid anywhere. */ 00311 if (name_has_wildcard && !allow_wcard_last_component) { 00312 return NT_STATUS_OBJECT_NAME_INVALID; 00313 } 00314 00315 /* Wildcards never valid within a pathname. */ 00316 if (name_has_wildcard && end) { 00317 return NT_STATUS_OBJECT_NAME_INVALID; 00318 } 00319 00320 /* 00321 * Check if the name exists up to this point. 00322 */ 00323 00324 if (SMB_VFS_STAT(conn,name, &st) == 0) { 00325 /* 00326 * It exists. it must either be a directory or this must be 00327 * the last part of the path for it to be OK. 00328 */ 00329 if (end && !(st.st_mode & S_IFDIR)) { 00330 /* 00331 * An intermediate part of the name isn't a directory. 00332 */ 00333 DEBUG(5,("Not a dir %s\n",start)); 00334 *end = '/'; 00335 /* 00336 * We need to return the fact that the intermediate 00337 * name resolution failed. This is used to return an 00338 * error of ERRbadpath rather than ERRbadfile. Some 00339 * Windows applications depend on the difference between 00340 * these two errors. 00341 */ 00342 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 00343 } 00344 00345 if (!end) { 00346 /* 00347 * We just scanned for, and found the end of the path. 00348 * We must return the valid stat struct. 00349 * JRA. 00350 */ 00351 00352 *pst = st; 00353 } 00354 00355 } else { 00356 pstring rest; 00357 00358 /* Stat failed - ensure we don't use it. */ 00359 SET_STAT_INVALID(st); 00360 *rest = 0; 00361 00362 /* 00363 * Remember the rest of the pathname so it can be restored 00364 * later. 00365 */ 00366 00367 if (end) { 00368 pstrcpy(rest,end+1); 00369 } 00370 00371 /* Reset errno so we can detect directory open errors. */ 00372 errno = 0; 00373 00374 /* 00375 * Try to find this part of the path in the directory. 00376 */ 00377 00378 if (name_has_wildcard || 00379 !scan_directory(conn, dirpath, start, sizeof(pstring) - 1 - (start - name))) { 00380 if (end) { 00381 /* 00382 * An intermediate part of the name can't be found. 00383 */ 00384 DEBUG(5,("Intermediate not found %s\n",start)); 00385 *end = '/'; 00386 00387 /* 00388 * We need to return the fact that the intermediate 00389 * name resolution failed. This is used to return an 00390 * error of ERRbadpath rather than ERRbadfile. Some 00391 * Windows applications depend on the difference between 00392 * these two errors. 00393 */ 00394 00395 /* ENOENT, ENOTDIR and ELOOP all map to 00396 * NT_STATUS_OBJECT_PATH_NOT_FOUND 00397 * in the filename walk. */ 00398 00399 if (errno == ENOENT || 00400 errno == ENOTDIR || 00401 errno == ELOOP) { 00402 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 00403 } 00404 return map_nt_error_from_unix(errno); 00405 } 00406 00407 /* ENOENT is the only valid error here. */ 00408 if ((errno != 0) && (errno != ENOENT) && (errno != EACCES)) { 00409 /* ENOTDIR and ELOOP both map to 00410 * NT_STATUS_OBJECT_PATH_NOT_FOUND 00411 * in the filename walk. */ 00412 if (errno == ENOTDIR || 00413 errno == ELOOP) { 00414 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 00415 } 00416 return map_nt_error_from_unix(errno); 00417 } 00418 00419 /* 00420 * Just the last part of the name doesn't exist. 00421 * We need to strupper() or strlower() it as 00422 * this conversion may be used for file creation 00423 * purposes. Fix inspired by Thomas Neumann <t.neumann@iku-ag.de>. 00424 */ 00425 if (!conn->case_preserve || 00426 (mangle_is_8_3(start, False, conn->params) && 00427 !conn->short_case_preserve)) { 00428 strnorm(start, lp_defaultcase(SNUM(conn))); 00429 } 00430 00431 /* 00432 * check on the mangled stack to see if we can recover the 00433 * base of the filename. 00434 */ 00435 00436 if (mangle_is_mangled(start, conn->params)) { 00437 mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), conn->params); 00438 } 00439 00440 DEBUG(5,("New file %s\n",start)); 00441 return NT_STATUS_OK; 00442 } 00443 00444 /* 00445 * Restore the rest of the string. If the string was mangled the size 00446 * may have changed. 00447 */ 00448 if (end) { 00449 end = start + strlen(start); 00450 if (!safe_strcat(start, "/", sizeof(pstring) - 1 - (start - name)) || 00451 !safe_strcat(start, rest, sizeof(pstring) - 1 - (start - name))) { 00452 return map_nt_error_from_unix(ENAMETOOLONG); 00453 } 00454 *end = '\0'; 00455 } else { 00456 /* 00457 * We just scanned for, and found the end of the path. 00458 * We must return a valid stat struct if it exists. 00459 * JRA. 00460 */ 00461 00462 if (SMB_VFS_STAT(conn,name, &st) == 0) { 00463 *pst = st; 00464 } else { 00465 SET_STAT_INVALID(st); 00466 } 00467 } 00468 } /* end else */ 00469 00470 #ifdef DEVELOPER 00471 if (VALID_STAT(st) && get_delete_on_close_flag(st.st_dev, st.st_ino)) { 00472 return NT_STATUS_DELETE_PENDING; 00473 } 00474 #endif 00475 00476 /* 00477 * Add to the dirpath that we have resolved so far. 00478 */ 00479 if (*dirpath) { 00480 pstrcat(dirpath,"/"); 00481 } 00482 00483 pstrcat(dirpath,start); 00484 00485 /* 00486 * Don't cache a name with mangled or wildcard components 00487 * as this can change the size. 00488 */ 00489 00490 if(!component_was_mangled && !name_has_wildcard) { 00491 stat_cache_add(orig_path, dirpath, conn->case_sensitive); 00492 } 00493 00494 /* 00495 * Restore the / that we wiped out earlier. 00496 */ 00497 if (end) { 00498 *end = '/'; 00499 } 00500 } 00501 00502 /* 00503 * Don't cache a name with mangled or wildcard components 00504 * as this can change the size. 00505 */ 00506 00507 if(!component_was_mangled && !name_has_wildcard) { 00508 stat_cache_add(orig_path, name, conn->case_sensitive); 00509 } 00510 00511 /* 00512 * The name has been resolved. 00513 */ 00514 00515 DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); 00516 return NT_STATUS_OK; 00517 }
NTSTATUS check_name | ( | connection_struct * | conn, | |
const pstring | name | |||
) |
filename.c の 526 行で定義されています。
参照先 map_nt_error_from_unix()・nt_errstr()・reduce_name()・status.
参照元 _srv_net_file_query_secdesc()・_srv_net_file_set_secdesc()・call_nt_transact_create()・call_trans2findfirst()・call_trans2mkdir()・call_trans2open()・call_trans2qfilepathinfo()・call_trans2setfilepathinfo()・copy_internals()・dptr_create()・hardlink_internals()・mkdir_internal()・open_file_ntcreate()・rename_internals()・rename_internals_fsp()・reply_checkpath()・reply_copy()・reply_ctemp()・reply_getatr()・reply_mkdir()・reply_mknew()・reply_ntcreate_and_X()・reply_open()・reply_open_and_X()・reply_rmdir()・reply_search()・reply_setatr()・smb_set_file_unix_link()・unlink_internals().
00527 { 00528 if (IS_VETO_PATH(conn, name)) { 00529 /* Is it not dot or dot dot. */ 00530 if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) { 00531 DEBUG(5,("check_name: file path name %s vetoed\n",name)); 00532 return map_nt_error_from_unix(ENOENT); 00533 } 00534 } 00535 00536 if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) { 00537 NTSTATUS status = reduce_name(conn,name); 00538 if (!NT_STATUS_IS_OK(status)) { 00539 DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status))); 00540 return status; 00541 } 00542 } 00543 00544 return NT_STATUS_OK; 00545 }