smbd/dosmode.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    dos mode handling functions
00004    Copyright (C) Andrew Tridgell 1992-1998
00005    Copyright (C) James Peach 2006
00006    
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011    
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016    
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 */
00021 
00022 #include "includes.h"
00023 
00024 static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
00025 {
00026 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
00027         if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) {
00028                 return FILE_ATTRIBUTE_SPARSE;
00029         }
00030 #endif
00031         return 0;
00032 }
00033 
00034 /****************************************************************************
00035  Work out whether this file is offline
00036 ****************************************************************************/
00037 
00038 static uint32 set_offline_flag(connection_struct *conn, const char *const path)
00039 {
00040         if (ISDOT(path) || ISDOTDOT(path)) {
00041                 return 0;
00042         }
00043 
00044         if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
00045                 return 0;
00046         }
00047 
00048         return dmapi_file_flags(path);
00049 }
00050 
00051 /****************************************************************************
00052  Change a dos mode to a unix mode.
00053     Base permission for files:
00054          if creating file and inheriting (i.e. parent_dir != NULL)
00055            apply read/write bits from parent directory.
00056          else   
00057            everybody gets read bit set
00058          dos readonly is represented in unix by removing everyone's write bit
00059          dos archive is represented in unix by the user's execute bit
00060          dos system is represented in unix by the group's execute bit
00061          dos hidden is represented in unix by the other's execute bit
00062          if !inheriting {
00063            Then apply create mask,
00064            then add force bits.
00065          }
00066     Base permission for directories:
00067          dos directory is represented in unix by unix's dir bit and the exec bit
00068          if !inheriting {
00069            Then apply create mask,
00070            then add force bits.
00071          }
00072 ****************************************************************************/
00073 
00074 mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname,
00075                  const char *inherit_from_dir)
00076 {
00077         mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
00078         mode_t dir_mode = 0; /* Mode of the inherit_from directory if
00079                               * inheriting. */
00080 
00081         if (!lp_store_dos_attributes(SNUM(conn)) && IS_DOS_READONLY(dosmode)) {
00082                 result &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
00083         }
00084 
00085         if (fname && (inherit_from_dir != NULL)
00086             && lp_inherit_perms(SNUM(conn))) {
00087                 SMB_STRUCT_STAT sbuf;
00088 
00089                 DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname,
00090                           inherit_from_dir));
00091                 if (SMB_VFS_STAT(conn, inherit_from_dir, &sbuf) != 0) {
00092                         DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname,
00093                                  inherit_from_dir, strerror(errno)));
00094                         return(0);      /* *** shouldn't happen! *** */
00095                 }
00096 
00097                 /* Save for later - but explicitly remove setuid bit for safety. */
00098                 dir_mode = sbuf.st_mode & ~S_ISUID;
00099                 DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode));
00100                 /* Clear "result" */
00101                 result = 0;
00102         } 
00103 
00104         if (IS_DOS_DIR(dosmode)) {
00105                 /* We never make directories read only for the owner as under DOS a user
00106                 can always create a file in a read-only directory. */
00107                 result |= (S_IFDIR | S_IWUSR);
00108 
00109                 if (dir_mode) {
00110                         /* Inherit mode of parent directory. */
00111                         result |= dir_mode;
00112                 } else {
00113                         /* Provisionally add all 'x' bits */
00114                         result |= (S_IXUSR | S_IXGRP | S_IXOTH);                 
00115 
00116                         /* Apply directory mask */
00117                         result &= lp_dir_mask(SNUM(conn));
00118                         /* Add in force bits */
00119                         result |= lp_force_dir_mode(SNUM(conn));
00120                 }
00121         } else { 
00122                 if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode))
00123                         result |= S_IXUSR;
00124 
00125                 if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode))
00126                         result |= S_IXGRP;
00127  
00128                 if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode))
00129                         result |= S_IXOTH;  
00130 
00131                 if (dir_mode) {
00132                         /* Inherit 666 component of parent directory mode */
00133                         result |= dir_mode & (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
00134                 } else {
00135                         /* Apply mode mask */
00136                         result &= lp_create_mask(SNUM(conn));
00137                         /* Add in force bits */
00138                         result |= lp_force_create_mode(SNUM(conn));
00139                 }
00140         }
00141 
00142         DEBUG(3,("unix_mode(%s) returning 0%o\n",fname,(int)result ));
00143         return(result);
00144 }
00145 
00146 /****************************************************************************
00147  Change a unix mode to a dos mode.
00148 ****************************************************************************/
00149 
00150 static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
00151 {
00152         int result = 0;
00153         enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn));
00154 
00155         if (ro_opts == MAP_READONLY_YES) {
00156                 /* Original Samba method - map inverse of user "w" bit. */
00157                 if ((sbuf->st_mode & S_IWUSR) == 0) {
00158                         result |= aRONLY;
00159                 }
00160         } else if (ro_opts == MAP_READONLY_PERMISSIONS) {
00161                 /* Check actual permissions for read-only. */
00162                 if (!can_write_to_file(conn, path, sbuf)) {
00163                         result |= aRONLY;
00164                 }
00165         } /* Else never set the readonly bit. */
00166 
00167         if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0))
00168                 result |= aARCH;
00169 
00170         if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0))
00171                 result |= aSYSTEM;
00172         
00173         if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0))
00174                 result |= aHIDDEN;   
00175   
00176         if (S_ISDIR(sbuf->st_mode))
00177                 result = aDIR | (result & aRONLY);
00178 
00179         result |= set_sparse_flag(sbuf);
00180  
00181 #ifdef S_ISLNK
00182 #if LINKS_READ_ONLY
00183         if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
00184                 result |= aRONLY;
00185 #endif
00186 #endif
00187 
00188         DEBUG(8,("dos_mode_from_sbuf returning "));
00189 
00190         if (result & aHIDDEN) DEBUG(8, ("h"));
00191         if (result & aRONLY ) DEBUG(8, ("r"));
00192         if (result & aSYSTEM) DEBUG(8, ("s"));
00193         if (result & aDIR   ) DEBUG(8, ("d"));
00194         if (result & aARCH  ) DEBUG(8, ("a"));
00195         
00196         DEBUG(8,("\n"));
00197         return result;
00198 }
00199 
00200 /****************************************************************************
00201  Get DOS attributes from an EA.
00202 ****************************************************************************/
00203 
00204 static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr)
00205 {
00206         ssize_t sizeret;
00207         fstring attrstr;
00208         unsigned int dosattr;
00209 
00210         if (!lp_store_dos_attributes(SNUM(conn))) {
00211                 return False;
00212         }
00213 
00214         /* Don't reset pattr to zero as we may already have filename-based attributes we
00215            need to preserve. */
00216 
00217         sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr));
00218         if (sizeret == -1) {
00219 #if defined(ENOTSUP) && defined(ENOATTR)
00220                 if ((errno != ENOTSUP) && (errno != ENOATTR) && (errno != EACCES) && (errno != EPERM)) {
00221                         DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
00222                                 path, strerror(errno) ));
00223                         set_store_dos_attributes(SNUM(conn), False);
00224                 }
00225 #endif
00226                 return False;
00227         }
00228         /* Null terminate string. */
00229         attrstr[sizeret] = 0;
00230         DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path, attrstr));
00231 
00232         if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' ||
00233                         sscanf(attrstr, "%x", &dosattr) != 1) {
00234                 DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path, attrstr));
00235                 return False;
00236         }
00237 
00238         if (S_ISDIR(sbuf->st_mode)) {
00239                 dosattr |= aDIR;
00240         }
00241         *pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK);
00242 
00243         DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
00244 
00245         if (dosattr & aHIDDEN) DEBUG(8, ("h"));
00246         if (dosattr & aRONLY ) DEBUG(8, ("r"));
00247         if (dosattr & aSYSTEM) DEBUG(8, ("s"));
00248         if (dosattr & aDIR   ) DEBUG(8, ("d"));
00249         if (dosattr & aARCH  ) DEBUG(8, ("a"));
00250         
00251         DEBUG(8,("\n"));
00252 
00253         return True;
00254 }
00255 
00256 /****************************************************************************
00257  Set DOS attributes in an EA.
00258 ****************************************************************************/
00259 
00260 static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode)
00261 {
00262         fstring attrstr;
00263         files_struct *fsp = NULL;
00264         BOOL ret = False;
00265 
00266         if (!lp_store_dos_attributes(SNUM(conn))) {
00267                 return False;
00268         }
00269 
00270         snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK);
00271         if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) {
00272                 if((errno != EPERM) && (errno != EACCES)) {
00273                         if (errno == ENOSYS
00274 #if defined(ENOTSUP)
00275                                 || errno == ENOTSUP) {
00276 #else
00277                                 ) {
00278 #endif
00279                                 set_store_dos_attributes(SNUM(conn), False);
00280                         }
00281                         return False;
00282                 }
00283 
00284                 /* We want DOS semantics, ie allow non owner with write permission to change the
00285                         bits on a file. Just like file_ntimes below.
00286                 */
00287 
00288                 /* Check if we have write access. */
00289                 if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
00290                         return False;
00291 
00292                 /*
00293                  * We need to open the file with write access whilst
00294                  * still in our current user context. This ensures we
00295                  * are not violating security in doing the setxattr.
00296                  */
00297 
00298                 if (!NT_STATUS_IS_OK(open_file_fchmod(conn,path,sbuf,&fsp)))
00299                         return ret;
00300                 become_root();
00301                 if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) {
00302                         ret = True;
00303                 }
00304                 unbecome_root();
00305                 close_file_fchmod(fsp);
00306                 return ret;
00307         }
00308         DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path));
00309         return True;
00310 }
00311 
00312 /****************************************************************************
00313  Change a unix mode to a dos mode for an ms dfs link.
00314 ****************************************************************************/
00315 
00316 uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
00317 {
00318         uint32 result = 0;
00319 
00320         DEBUG(8,("dos_mode_msdfs: %s\n", path));
00321 
00322         if (!VALID_STAT(*sbuf)) {
00323                 return 0;
00324         }
00325 
00326         /* First do any modifications that depend on the path name. */
00327         /* hide files with a name starting with a . */
00328         if (lp_hide_dot_files(SNUM(conn))) {
00329                 const char *p = strrchr_m(path,'/');
00330                 if (p) {
00331                         p++;
00332                 } else {
00333                         p = path;
00334                 }
00335                 
00336                 if (p[0] == '.' && p[1] != '.' && p[1] != 0) {
00337                         result |= aHIDDEN;
00338                 }
00339         }
00340         
00341         result |= dos_mode_from_sbuf(conn, path, sbuf);
00342 
00343         /* Optimization : Only call is_hidden_path if it's not already
00344            hidden. */
00345         if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
00346                 result |= aHIDDEN;
00347         }
00348 
00349         DEBUG(8,("dos_mode_msdfs returning "));
00350 
00351         if (result & aHIDDEN) DEBUG(8, ("h"));
00352         if (result & aRONLY ) DEBUG(8, ("r"));
00353         if (result & aSYSTEM) DEBUG(8, ("s"));
00354         if (result & aDIR   ) DEBUG(8, ("d"));
00355         if (result & aARCH  ) DEBUG(8, ("a"));
00356         if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
00357         
00358         DEBUG(8,("\n"));
00359 
00360         return(result);
00361 }
00362 
00363 /****************************************************************************
00364  Change a unix mode to a dos mode.
00365 ****************************************************************************/
00366 
00367 uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
00368 {
00369         uint32 result = 0;
00370 
00371         DEBUG(8,("dos_mode: %s\n", path));
00372 
00373         if (!VALID_STAT(*sbuf)) {
00374                 return 0;
00375         }
00376 
00377         /* First do any modifications that depend on the path name. */
00378         /* hide files with a name starting with a . */
00379         if (lp_hide_dot_files(SNUM(conn))) {
00380                 const char *p = strrchr_m(path,'/');
00381                 if (p) {
00382                         p++;
00383                 } else {
00384                         p = path;
00385                 }
00386                 
00387                 if (p[0] == '.' && p[1] != '.' && p[1] != 0) {
00388                         result |= aHIDDEN;
00389                 }
00390         }
00391         
00392         /* Get the DOS attributes from an EA by preference. */
00393         if (get_ea_dos_attribute(conn, path, sbuf, &result)) {
00394                 result |= set_sparse_flag(sbuf);
00395         } else {
00396                 result |= dos_mode_from_sbuf(conn, path, sbuf);
00397         }
00398 
00399         if (S_ISREG(sbuf->st_mode)) {
00400                 result |= set_offline_flag(conn, path);
00401         }
00402 
00403         /* Optimization : Only call is_hidden_path if it's not already
00404            hidden. */
00405         if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
00406                 result |= aHIDDEN;
00407         }
00408 
00409         DEBUG(8,("dos_mode returning "));
00410 
00411         if (result & aHIDDEN) DEBUG(8, ("h"));
00412         if (result & aRONLY ) DEBUG(8, ("r"));
00413         if (result & aSYSTEM) DEBUG(8, ("s"));
00414         if (result & aDIR   ) DEBUG(8, ("d"));
00415         if (result & aARCH  ) DEBUG(8, ("a"));
00416         if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
00417         
00418         DEBUG(8,("\n"));
00419 
00420         return(result);
00421 }
00422 
00423 /*******************************************************************
00424  chmod a file - but preserve some bits.
00425 ********************************************************************/
00426 
00427 int file_set_dosmode(connection_struct *conn, const char *fname,
00428                      uint32 dosmode, SMB_STRUCT_STAT *st,
00429                      const char *parent_dir)
00430 {
00431         SMB_STRUCT_STAT st1;
00432         int mask=0;
00433         mode_t tmp;
00434         mode_t unixmode;
00435         int ret = -1;
00436 
00437         /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
00438         dosmode &= SAMBA_ATTRIBUTES_MASK;
00439 
00440         DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
00441 
00442         if (st == NULL) {
00443                 SET_STAT_INVALID(st1);
00444                 st = &st1;
00445         }
00446 
00447         if (!VALID_STAT(*st)) {
00448                 if (SMB_VFS_STAT(conn,fname,st))
00449                         return(-1);
00450         }
00451 
00452         unixmode = st->st_mode;
00453 
00454         get_acl_group_bits(conn, fname, &st->st_mode);
00455 
00456         if (S_ISDIR(st->st_mode))
00457                 dosmode |= aDIR;
00458         else
00459                 dosmode &= ~aDIR;
00460 
00461         if (dos_mode(conn,fname,st) == dosmode) {
00462                 st->st_mode = unixmode;
00463                 return(0);
00464         }
00465 
00466         /* Store the DOS attributes in an EA by preference. */
00467         if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
00468                 st->st_mode = unixmode;
00469                 return 0;
00470         }
00471 
00472         unixmode = unix_mode(conn,dosmode,fname, parent_dir);
00473 
00474         /* preserve the s bits */
00475         mask |= (S_ISUID | S_ISGID);
00476 
00477         /* preserve the t bit */
00478 #ifdef S_ISVTX
00479         mask |= S_ISVTX;
00480 #endif
00481 
00482         /* possibly preserve the x bits */
00483         if (!MAP_ARCHIVE(conn))
00484                 mask |= S_IXUSR;
00485         if (!MAP_SYSTEM(conn))
00486                 mask |= S_IXGRP;
00487         if (!MAP_HIDDEN(conn))
00488                 mask |= S_IXOTH;
00489 
00490         unixmode |= (st->st_mode & mask);
00491 
00492         /* if we previously had any r bits set then leave them alone */
00493         if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
00494                 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
00495                 unixmode |= tmp;
00496         }
00497 
00498         /* if we previously had any w bits set then leave them alone 
00499                 whilst adding in the new w bits, if the new mode is not rdonly */
00500         if (!IS_DOS_READONLY(dosmode)) {
00501                 unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
00502         }
00503 
00504         if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) {
00505                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
00506                              FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
00507                 st->st_mode = unixmode;
00508                 return 0;
00509         }
00510 
00511         if((errno != EPERM) && (errno != EACCES))
00512                 return -1;
00513 
00514         if(!lp_dos_filemode(SNUM(conn)))
00515                 return -1;
00516 
00517         /* We want DOS semantics, ie allow non owner with write permission to change the
00518                 bits on a file. Just like file_ntimes below.
00519         */
00520 
00521         /* Check if we have write access. */
00522         if (CAN_WRITE(conn)) {
00523                 /*
00524                  * We need to open the file with write access whilst
00525                  * still in our current user context. This ensures we
00526                  * are not violating security in doing the fchmod.
00527                  * This file open does *not* break any oplocks we are
00528                  * holding. We need to review this.... may need to
00529                  * break batch oplocks open by others. JRA.
00530                  */
00531                 files_struct *fsp;
00532                 if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,st,&fsp)))
00533                         return -1;
00534                 become_root();
00535                 ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode);
00536                 unbecome_root();
00537                 close_file_fchmod(fsp);
00538                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
00539                              FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
00540                 if (ret == 0) {
00541                         st->st_mode = unixmode;
00542                 }
00543         }
00544 
00545         return( ret );
00546 }
00547 
00548 /*******************************************************************
00549  Wrapper around the VFS ntimes that possibly allows DOS semantics rather
00550  than POSIX.
00551 *******************************************************************/
00552 
00553 int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2])
00554 {
00555         SMB_STRUCT_STAT sbuf;
00556         int ret = -1;
00557 
00558         errno = 0;
00559         ZERO_STRUCT(sbuf);
00560 
00561         /* Don't update the time on read-only shares */
00562         /* We need this as set_filetime (which can be called on
00563            close and other paths) can end up calling this function
00564            without the NEED_WRITE protection. Found by : 
00565            Leo Weppelman <leo@wau.mis.ah.nl>
00566         */
00567 
00568         if (!CAN_WRITE(conn)) {
00569                 return 0;
00570         }
00571 
00572         if(SMB_VFS_NTIMES(conn, fname, ts) == 0) {
00573                 return 0;
00574         }
00575 
00576         if((errno != EPERM) && (errno != EACCES)) {
00577                 return -1;
00578         }
00579 
00580         if(!lp_dos_filetimes(SNUM(conn))) {
00581                 return -1;
00582         }
00583 
00584         /* We have permission (given by the Samba admin) to
00585            break POSIX semantics and allow a user to change
00586            the time on a file they don't own but can write to
00587            (as DOS does).
00588          */
00589 
00590         /* Check if we have write access. */
00591         if (can_write_to_file(conn, fname, &sbuf)) {
00592                 /* We are allowed to become root and change the filetime. */
00593                 become_root();
00594                 ret = SMB_VFS_NTIMES(conn, fname, ts);
00595                 unbecome_root();
00596         }
00597 
00598         return ret;
00599 }
00600   
00601 /*******************************************************************
00602  Change a filetime - possibly allowing DOS semantics.
00603 *******************************************************************/
00604 
00605 BOOL set_filetime(connection_struct *conn, const char *fname,
00606                 const struct timespec mtime)
00607 {
00608         struct timespec ts[2];
00609 
00610         if (null_timespec(mtime)) {
00611                 return(True);
00612         }
00613 
00614         ts[1] = mtime; /* mtime. */
00615         ts[0] = ts[1]; /* atime. */
00616 
00617         if (file_ntimes(conn, fname, ts)) {
00618                 DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
00619                 return False;
00620         }
00621 
00622         notify_fname(conn, NOTIFY_ACTION_MODIFIED,
00623                      FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
00624   
00625         return True;
00626 }

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