smbd/filename.c

ソースコードを見る。

関数

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.c552 行で定義されています。

参照先 connection_struct::case_sensitiveCloseDir()smb_Dir::conncur_direrrnofname_equal()mangle_check_cache()mangle_is_mangled()mangled_equal()OpenDir()connection_struct::paramsReadDirName().

参照元 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 }

static BOOL fname_equal ( const char *  name1,
const char *  name2,
BOOL  case_sensitive 
) [static]

filename.c36 行で定義されています。

参照先 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.c49 行で定義されています。

参照先 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.c63 行で定義されています。

参照先 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.c120 行で定義されています。

参照先 connection_struct::case_preserveconnection_struct::case_sensitivedetermine_path_error()errnoget_delete_on_close_flag()mangle_check_cache()mangle_is_8_3()mangle_is_mangled()map_nt_error_from_unix()ms_has_wild()connection_struct::paramsconnection_struct::printerscan_directory()connection_struct::short_case_preservestat_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.c526 行で定義されています。

参照先 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 }


Sambaに対してSat Aug 29 21:24:25 2009に生成されました。  doxygen 1.4.7