'dos filetimes' parameter for UTIME fix.
locking_shm.c: Fixed typo (sorry Andrew :-).
namepacket.c: Changed lp_interfaces_only() to lp_bind_interfaces_only().
proto.h: The usual.
reply.c: Made filetime calls use new file_utime call (wrapper for sys_utime).
server.c: Made filetime calls use new file_utime call (wrapper for sys_utime).
system.c: Added Andrew's sanity checks to times in sys_utime().
time.c: Moved set_filetime() to server.c. Made null_mtime() global.
trans2.c: Made filetime calls use new file_utime call (wrapper for sys_utime).
Jeremy (jallison@whistle.com)
BOOL lp_unix_realname(void);
BOOL lp_nis_home_map(void);
BOOL lp_time_server(void);
-BOOL lp_interfaces_only(void);
+BOOL lp_bind_interfaces_only(void);
int lp_os_level(void);
int lp_max_ttl(void);
int lp_max_log_size(void);
BOOL lp_delete_readonly(int );
BOOL lp_fake_oplocks(int );
BOOL lp_recursive_veto_delete(int );
+BOOL lp_dos_filetimes(int );
int lp_create_mode(int );
int lp_force_create_mode(int );
int lp_dir_mode(int );
mode_t unix_mode(int cnum,int dosmode);
int dos_mode(int cnum,char *path,struct stat *sbuf);
int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st);
+int file_utime(int cnum, char *fname, struct utimbuf *times);
+BOOL set_filetime(int cnum, char *fname, time_t mtime);
BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path);
int disk_free(char *path,int *bsize,int *dfree,int *dsize);
int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize);
struct tm *LocalTime(time_t *t);
time_t interpret_long_date(char *p);
void put_long_date(char *p,time_t t);
+BOOL null_mtime(time_t mtime);
void put_dos_date(char *buf,int offset,time_t unixdate);
void put_dos_date2(char *buf,int offset,time_t unixdate);
void put_dos_date3(char *buf,int offset,time_t unixdate);
time_t make_unix_date(void *date_ptr);
time_t make_unix_date2(void *date_ptr);
time_t make_unix_date3(void *date_ptr);
-BOOL set_filetime(char *fname,time_t mtime);
char *timestring(void );
/*The following definitions come from trans2.c */
********************************************************************/
int sys_utime(char *fname,struct utimbuf *times)
{
+ /* if the modtime is 0 or -1 then ignore the call and
+ return success */
+ if (times->modtime == (time_t)0 || times->modtime == (time_t)-1)
+ return 0;
+
+ /* if the access time is 0 or -1 then set it to the modtime */
+ if (times->actime == (time_t)0 || times->actime == (time_t)-1)
+ times->actime = times->modtime;
+
return(utime(dos_to_unix(fname,False),times));
}
/****************************************************************************
check if it's a null mtime
****************************************************************************/
-static BOOL null_mtime(time_t mtime)
+BOOL null_mtime(time_t mtime)
{
if (mtime == 0 || mtime == 0xFFFFFFFF || mtime == (time_t)-1)
return(True);
return(t);
}
-/****************************************************************************
-set the time on a file
-****************************************************************************/
-BOOL set_filetime(char *fname,time_t mtime)
-{
- struct utimbuf times;
-
- if (null_mtime(mtime)) return(True);
-
- times.modtime = times.actime = mtime;
-
- if (sys_utime(fname,×)) {
- DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
- }
-
- return(True);
-}
-
-
/****************************************************************************
return the date and time as a string
****************************************************************************/
/*******************************************************************
call the specified function on each entry under management by the
-share ode system
+share mode system
********************************************************************/
static int shm_share_forall(void (*fn)(share_mode_entry *, char *))
{
* If we got a packet on the broadcast socket and interfaces
* only is set then check it came from one of our local nets.
*/
- if(lp_interfaces_only() && (sock_array[i] == ClientNMB) &&
+ if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) &&
(!is_local_net(packet->ip)))
{
DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n",
* If we got a packet on the broadcast socket and interfaces
* only is set then check it came from one of our local nets.
*/
- if(lp_interfaces_only() && (sock_array[i] == ClientDGRAM) &&
+ if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) &&
(!is_local_net(packet->ip)))
{
DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n",
BOOL bUnixRealname;
BOOL bNISHomeMap;
BOOL bTimeServer;
- BOOL bInterfacesOnly;
+ BOOL bBindInterfacesOnly;
} global;
static global Globals;
BOOL bDeleteReadonly;
BOOL bFakeOplocks;
BOOL bDeleteVetoFiles;
+ BOOL bDosFiletimes;
char dummy[3]; /* for alignment */
} service;
False, /* bDeleteReadonly */
False, /* bFakeOplocks */
False, /* bDeleteVetoFiles */
+ False, /* bDosFiletimes */
"" /* dummy */
};
{"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL},
{"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL},
{"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL},
- {"interfaces only", P_BOOL, P_GLOBAL, &Globals.bInterfacesOnly, NULL},
+ {"bind interfaces only", P_BOOL,P_GLOBAL, &Globals.bBindInterfacesOnly,NULL},
{"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL},
{"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL},
{"netbios name", P_UGSTRING,P_GLOBAL, myname, NULL},
{"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL},
{"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL},
{"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL},
+ {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL},
{NULL, P_BOOL, P_NONE, NULL, NULL}
};
coding_system = interpret_coding_system (KANJI, SJIS_CODE);
Globals.client_code_page = DEFAULT_CLIENT_CODE_PAGE;
Globals.bTimeServer = False;
- Globals.bInterfacesOnly = False;
+ Globals.bBindInterfacesOnly = False;
/* these parameters are set to defaults that are more appropriate
for the increasing samba install base:
FN_GLOBAL_BOOL(lp_unix_realname,&Globals.bUnixRealname)
FN_GLOBAL_BOOL(lp_nis_home_map,&Globals.bNISHomeMap)
FN_GLOBAL_BOOL(lp_time_server,&Globals.bTimeServer)
-FN_GLOBAL_BOOL(lp_interfaces_only,&Globals.bInterfacesOnly)
+FN_GLOBAL_BOOL(lp_bind_interfaces_only,&Globals.bBindInterfacesOnly)
FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks)
FN_LOCAL_BOOL(lp_recursive_veto_delete,bDeleteVetoFiles)
+FN_LOCAL_BOOL(lp_dos_filetimes,bDosFiletimes)
FN_LOCAL_INTEGER(lp_create_mode,iCreate_mask)
FN_LOCAL_INTEGER(lp_force_create_mode,iCreate_force_mode)
if (check_name(fname,cnum))
ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
if (ok)
- ok = set_filetime(fname,mtime);
+ ok = set_filetime(cnum,fname,mtime);
if (!ok)
{
mtime = make_unix_date3(inbuf+smb_vwv1);
/* try and set the date */
- set_filetime(Files[fnum].name,mtime);
+ set_filetime(cnum, Files[fnum].name,mtime);
close_file(fnum,True);
nwritten = write_file(fnum,data,numtowrite);
- set_filetime(Files[fnum].name,mtime);
+ set_filetime(cnum, Files[fnum].name,mtime);
close_file(fnum,True);
}
/* Set the date on this file */
- if(sys_utime(Files[fnum].name, &unix_times))
+ if(file_utime(cnum, Files[fnum].name, &unix_times))
return(ERROR(ERRDOS,ERRnoaccess));
DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
return(result);
}
-
/*******************************************************************
chmod a file - but preserve some bits
********************************************************************/
return(sys_chmod(fname,unixmode));
}
+/*******************************************************************
+Wrapper around sys_utime that possibly allows DOS semantics rather
+than POSIX.
+*******************************************************************/
+
+int file_utime(int cnum, char *fname, struct utimbuf *times)
+{
+ extern struct current_user current_user;
+ struct stat sb;
+ int ret = -1;
+
+ if(sys_utime(fname, times) == 0)
+ return 0;
+
+ if((errno != EPERM) || !lp_dos_filetimes(SNUM(cnum)))
+ return -1;
+
+ /* We have permission (given by the Samba admin) to
+ break POSIX semantics and allow a user to change
+ the time on a file they don't own but can write to
+ (as DOS does).
+ */
+
+ if(sys_stat(fname,&sb) != 0)
+ return -1;
+
+ /* Check if we have write access. */
+ if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum)))
+ {
+ if (((sb.st_mode & S_IWOTH) ||
+ Connections[cnum].admin_user ||
+ ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) ||
+ ((sb.st_mode & S_IWGRP) &&
+ in_group(sb.st_gid,current_user.gid,
+ current_user.ngroups,current_user.igroups))))
+ {
+ /* We are allowed to become root and change the filetime. */
+ become_root(False);
+ ret = sys_utime(fname, times);
+ unbecome_root(False);
+ }
+ }
+
+ return ret;
+}
+
+/*******************************************************************
+Change a filetime - possibly allowing DOS semantics.
+*******************************************************************/
+
+BOOL set_filetime(int cnum, char *fname, time_t mtime)
+{
+ struct utimbuf times;
+
+ if (null_mtime(mtime)) return(True);
+
+ times.modtime = times.actime = mtime;
+
+ if (file_utime(cnum, fname, ×)) {
+ DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
+ }
+
+ return(True);
+}
/****************************************************************************
check if two filenames are equal
DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
*/
-#if UTIME_WORKAROUND
- /* XXXX - is this OK?? */
- /* this works around a utime bug but can cause other problems */
- if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
- sys_unlink(fname);
-#endif
-
/*
* Ensure we have a valid struct stat so we can search the
* open fd table.
*/
if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
{
- if(sys_utime(fname, &tvs)!=0)
+ if(file_utime(cnum, fname, &tvs)!=0)
{
return(ERROR(ERRDOS,ERRnoaccess));
}