diff -u -r --new-file --exclude=CVS source/Makefile newsource/Makefile --- source/Makefile Tue Oct 21 12:47:16 1997 +++ newsource/Makefile Mon Oct 27 15:46:39 1997 @@ -636,7 +636,7 @@ SMBDOBJ = predict.o clientgen.o $(SMBDOBJ1) $(SMBDOBJ2) $(VTP_OBJ) NMBDOBJ1 = nmblib.o namepacket.o nameresp.o nmbsync.o nameannounce.o nameelect.o NMBDOBJ2 = namedbresp.o namedbwork.o namedbserver.o namedbsubnet.o namedbname.o -NMBDOBJ3 = nameservresp.o nameservreply.o namelogon.o namebrowse.o namework.o nameserv.o clientutil.o +NMBDOBJ3 = nameservresp.o nameservreply.o namelogon.o namebrowse.o namework.o nameserv.o clientutil.o namelanman.o NMBDOBJ = $(UTILOBJ) $(NMBDOBJ1) $(NMBDOBJ2) $(NMBDOBJ3) .SUFFIXES: .SUFFIXES: .c .o .h diff -u -r --new-file --exclude=CVS source/client.c newsource/client.c --- source/client.c Tue Oct 21 12:47:16 1997 +++ newsource/client.c Mon Oct 27 15:46:40 1997 @@ -1298,6 +1298,11 @@ (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300)))) method = 0; + /* Attempt to detect OS/2 Peer as the server, because it can crash + on a chained readX+close. */ + if (max_xmit == 4356) + method = -1; + /* if we support readraw then use that */ if (method<0 && readbraw_supported) method = 1; diff -u -r --new-file --exclude=CVS source/loadparm.c newsource/loadparm.c --- source/loadparm.c Tue Oct 21 12:47:17 1997 +++ newsource/loadparm.c Mon Oct 27 15:46:40 1997 @@ -153,6 +153,8 @@ int os_level; int max_ttl; int ReadSize; + int lm_announce; + int lm_interval; int shmem_size; int shmem_hash_size; int client_code_page; @@ -471,6 +473,8 @@ {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL}, {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL}, {"unix realname", P_BOOL, P_GLOBAL, &Globals.bUnixRealname, NULL}, + {"lm announce", P_INTEGER, P_GLOBAL, &Globals.lm_announce, NULL}, + {"lm interval", P_INTEGER, P_GLOBAL, &Globals.lm_interval, NULL}, {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL}, {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL}, {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL}, @@ -641,6 +645,8 @@ Globals.os_level = 0; Globals.max_ttl = 60*60*4; /* 2 hours default */ Globals.ReadSize = 16*1024; + Globals.lm_announce = 2; /* = Auto: send only if LM clients found */ + Globals.lm_interval = 60; Globals.shmem_size = SHMEM_SIZE; Globals.shmem_hash_size = SHMEM_HASH_SIZE; Globals.announce_as = ANNOUNCE_AS_NT; @@ -884,6 +890,8 @@ FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize) FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime) FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog) +FN_GLOBAL_INTEGER(lp_lm_announce,&Globals.lm_announce) +FN_GLOBAL_INTEGER(lp_lm_interval,&Globals.lm_interval) FN_GLOBAL_INTEGER(lp_client_code_page,&Globals.client_code_page) FN_GLOBAL_INTEGER(lp_announce_as,&Globals.announce_as) diff -u -r --new-file --exclude=CVS source/namelanman.c newsource/namelanman.c --- source/namelanman.c +++ newsource/namelanman.c Mon Oct 27 16:12:34 1997 @@ -0,0 +1,309 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + NBT netbios routines and daemon - version 2 + Copyright (C) Andrew Tridgell 1994-1997 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Revision History: + + 27 mar 1997: Andreas Degert + Implementation of LAN Manager (LM) announcements. + Samba servers should now be visible to LM clients + (including OS/2 machines). + 14 apr 1997: Jacco de Leeuw + Observed OS/2 machines will be added to the browse list. + All LM routines have been moved to one file. + 5 may 1997: Send LM announcements with no services when Samba is killed. + Renamed LM routines to resemble existing name scheme. [JdL] + 11 aug 1997: Updated for 1.9.17. [JdL] + 15 oct 1997: Added "auto" enabling of sending LM announcements. [JdL] +*/ + +#include "includes.h" + +extern int ClientDGRAM; +extern pstring myname; +extern struct subnet_record *subnetlist; +extern struct in_addr wins_ip; +extern int DEBUGLEVEL; +extern pstring scope; +extern BOOL updatedlists; + +static BOOL found_lm_clients = False; + +/**************************************************************************** + send a LAN Manager packet + **************************************************************************/ + +void do_announce_lm_host(int command, + char *from_name, int from_type, + struct in_addr from_ip, char *to_name, + int to_type, struct in_addr to_ip, + time_t announce_interval, char *server_name, + int server_type, char *server_comment) +{ + pstring outbuf; + char *p = outbuf; + + bzero(outbuf,sizeof(outbuf)); + + SSVAL(p,0,command); /* frame type */ + SIVAL(p,2,server_type); /* services offered by this server */ + CVAL(p,6) = lp_major_announce_version(); + CVAL(p,7) = lp_minor_announce_version(); + SSVAL(p,8,announce_interval); /* announcement cycle in seconds */ + p += 10; + strcpy(p,server_name); + strupper(p); + p = skip_string(p,1); + strcpy(p,server_comment); + p = skip_string(p,1); + + debug_browse_data(outbuf, PTR_DIFF(p,outbuf)); + + /* send the announcement */ + send_mailslot_reply(False,LANMAN_MAILSLOT,ClientDGRAM,outbuf, + PTR_DIFF(p,outbuf), + from_name, to_name, + from_type, to_type, + to_ip, from_ip); +} + + +/**************************************************************************** + announce on all subnets that Samba is no longer a LAN Manager server + **************************************************************************/ + +void announce_my_lm_servers_removed(void) +{ + char *work = lp_workgroup(); + int announce_interval = lp_lm_interval(); + int lm_announce = lp_lm_announce(); + struct subnet_record *d; + int server_type; + pstring comment; + + if ((announce_interval <= 0) || (lm_announce <= 0)) + return; /* user absolutely does not want LM announcements to be send */ + if ((lm_announce >= 2) && (!found_lm_clients)) + return; /* has been set to 2 (Auto) but no LM clients detected (yet) */ + /* Otherwise: must have been set to 1 (Yes), or LM clients *have* + been detected */ + + StrnCpy(comment, lp_serverstring(), 43); + + if (myname[0] == '\0') return; + + server_type = 0; /* Going down. There are 'no services'. */ + + for (d = subnetlist; d; d = d->next) + { + if (ip_equal(d->bcast_ip, wins_ip)) continue; + announce_lm_server(d,work,myname,comment, + announce_interval,server_type); + } +} + + +/**************************************************************************** + send a LAN Manager host announcement packet + **************************************************************************/ + +void announce_lm_server(struct subnet_record *d, char *work, + char *name, char *comment, time_t ttl, int server_type) +{ + + do_announce_lm_host(ANN_HostAnnouncement, + name, 0x00, + d->myip, work, + 0x00, d->bcast_ip, + ttl, name, + server_type, comment); +} + + +/**************************************************************************** + announce a LAN Manager server entry on all subnets + **************************************************************************/ + +void announce_lm_host(time_t t) +{ + static time_t lastannounce_time = 0; + char *work = lp_workgroup(); + int announce_interval = lp_lm_interval(); + int lm_announce = lp_lm_announce(); + struct subnet_record *d; + int server_type; + pstring comment; + + if ((announce_interval <= 0) || (lm_announce <= 0)) + return; /* user absolutely does not want LM announcements to be send */ + if ((lm_announce >= 2) && (!found_lm_clients)) + return; /* has been set to 2 (Auto) but no LM clients detected (yet) */ + /* Otherwise: must have been set to 1 (Yes), or LM clients *have* + been detected */ + + StrnCpy(comment, lp_serverstring(), 43); + + if (myname[0] == '\0') return; + + if (lastannounce_time && (t - lastannounce_time) < announce_interval) + return; + + lastannounce_time = t; + server_type = SV_TYPE_WORKSTATION|SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE; + + for (d = subnetlist; d; d = d->next) + { + if (ip_equal(d->bcast_ip, wins_ip)) continue; + announce_lm_server(d,work,myname,comment, + announce_interval,server_type); + } +} + + + /******************************************************************* + process a LAN Manager announcement frame + ******************************************************************/ +static void process_lm_announce(struct packet_struct *p,uint16 command,char *buf) +{ + struct dgram_packet *dgram = &p->packet.dgram; + struct in_addr ip = dgram->header.source_ip; + struct subnet_record *d = find_subnet(ip); + + int ttl = SVAL(buf,8); /* time-to-live for this announcement */ + char *name = buf+10; + int osmajor=CVAL(buf,6); /* major version of node software */ + int osminor=CVAL(buf,7); /* minor version of node software */ + uint32 server_type = IVAL(buf,2); /* services offered by this server */ + char *s = buf+10; + pstring comment; + static int logwarnings=0; + + struct work_record *work; + char *work_name; + char *serv_name = dgram->source_name.name; + BOOL add = False; + + s = skip_string(s,1); + StrnCpy(comment, s, 43); + + DEBUG(4,("LM Announcement(%d) from %s",command,name)); + DEBUG(4,(" on %s ttl=%d OS=(%d,%d) type=%08x comment=%s\n", + namestr(&dgram->dest_name),ttl,osmajor,osminor, + server_type,comment)); + + if (((osmajor > 38) && (osmajor < 36)) || (osminor !=0)) + { + DEBUG(4,("LM Announcement frame discarded: didn't originate from" \ + " OS/2 Warp 4 or Connect\n")); + /* Could have been from a Windows machine (with LM Announce=Yes), + or a Samba server. Then don't disrupt the current browse list. */ + return; + } + + if (!strequal(dgram->dest_name.scope,scope )) return; + + found_lm_clients = True; + + /* we need some way of finding out about new workgroups + that appear to be sending packets to us. The name_type checks make + sure we don't add host names as workgroups */ + if (command == ANN_HostAnnouncement && + (dgram->dest_name.name_type == 0x1d || + dgram->dest_name.name_type == 0x1e)) + add = True; + + work_name = dgram->dest_name.name; + if (!(work = find_workgroupstruct(d, work_name,add))) + return; + + DEBUG(4, ("workgroup %s on %s\n", work->work_group, serv_name)); + + ttl = GET_TTL(ttl); + + /* add them to our browse list, and update the browse.dat file */ + add_server_entry(d,work,name,server_type|SV_TYPE_LOCAL_LIST_ONLY,ttl,comment,True); + updatedlists = True; +} + + +/******************************************************************* + process a LAN Manager announcement request +*******************************************************************/ + +static void process_lm_announce_request(struct packet_struct *p,char *buf) +{ + pstring comment; + uint32 server_type; + int announce_interval = lp_lm_interval(); + + + if (announce_interval <= 0) + { + DEBUG(3,("ignoring LM announcement request from %s\n",buf+2)); + /* The server is configured to not send LM announcements */ + return; + } + + DEBUG(3,("responding to LM announcement request from %s\n",buf+2)); + + server_type = SV_TYPE_WORKSTATION|SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE; + + StrnCpy(comment, lp_serverstring(), 43); + + do_announce_lm_host(ANN_HostAnnouncement, + myname, 0x00, + *iface_ip(p->ip), lp_workgroup(), + 0x00, p->ip, + announce_interval, myname, + server_type, comment); +} + + +/**************************************************************************** + process a LAN Manager browse frame + **************************************************************************/ + +void process_lanman_packet(struct packet_struct *p,char *buf,int len) +{ + int code = SVAL(buf,0); + switch( code ) + { + case ANN_HostAnnouncement: + { + debug_browse_data(buf, len); + process_lm_announce(p, ANN_HostAnnouncement, buf); + break; + } + + case ANN_AnnouncementRequest: + { + debug_browse_data(buf, len); + process_lm_announce_request(p, buf); + break; + } + + default: + { + struct dgram_packet *dgram = &p->packet.dgram; + DEBUG(4,("unknown LM browse packet %d from %s %s to %s\n", + code, namestr(&dgram->source_name), + inet_ntoa(p->ip), namestr(&dgram->dest_name))); + } + } +} diff -u -r --new-file --exclude=CVS source/namepacket.c newsource/namepacket.c --- source/namepacket.c Thu Oct 16 03:57:37 1997 +++ newsource/namepacket.c Mon Oct 27 15:46:40 1997 @@ -387,6 +387,13 @@ process_logon_packet(p,buf2,len); return; } + + /* datagram packet received for the LAN Manager (OS/2) mailslot */ + if (strequal(smb_buf(buf),LANMAN_MAILSLOT)) { + process_lanman_packet(p,buf2,len); + return; + } + } /**************************************************************************** diff -u -r --new-file --exclude=CVS source/nameserv.h newsource/nameserv.h --- source/nameserv.h Thu Oct 16 03:57:37 1997 +++ newsource/nameserv.h Mon Oct 27 15:46:41 1997 @@ -82,6 +82,7 @@ /* mail slots */ #define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE" #define NET_LOGON_MAILSLOT "\\MAILSLOT\\NET\\NETLOGON" +#define LANMAN_MAILSLOT "\\MAILSLOT\\LANMAN" enum name_source {STATUS_QUERY, LMHOSTS, REGISTER, SELF, DNS, DNSFAIL}; enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3}; diff -u -r --new-file --exclude=CVS source/nmbd.c newsource/nmbd.c --- source/nmbd.c Fri Sep 26 14:39:42 1997 +++ newsource/nmbd.c Mon Oct 27 15:46:41 1997 @@ -71,6 +71,8 @@ /* XXXX don't care if we never receive a response back... yet */ announce_my_servers_removed(); + announce_my_lm_servers_removed(); + /* XXXX other things: if we are a master browser, force an election? */ exit(0); @@ -310,6 +312,7 @@ announce_host(t); announce_master(t); announce_remote(t); + announce_lm_host(t); query_refresh_names(t); diff -u -r --new-file --exclude=CVS source/proto.h newsource/proto.h --- source/proto.h Tue Oct 21 12:47:18 1997 +++ newsource/proto.h Mon Oct 27 15:46:41 1997 @@ -201,6 +201,8 @@ int lp_maxdisksize(void); int lp_lpqcachetime(void); int lp_syslog(void); +int lp_lm_announce(void); +int lp_lm_interval(void); int lp_client_code_page(void); int lp_announce_as(void); char *lp_preexec(int ); @@ -463,6 +465,20 @@ void run_elections(time_t t); void process_election(struct packet_struct *p,char *buf); BOOL check_elections(void); + +/*The following definitions come from namelanman.c */ + +void do_announce_lm_host(int command, + char *from_name, int from_type, + struct in_addr from_ip, char *to_name, + int to_type, struct in_addr to_ip, + time_t announce_interval, char *server_name, + int server_type, char *server_comment); +void announce_my_lm_servers_removed(void); +void announce_lm_server(struct subnet_record *d, char *work, + char *name, char *comment, time_t ttl, int server_type); +void announce_lm_host(time_t t); +void process_lanman_packet(struct packet_struct *p,char *buf,int len); /*The following definitions come from namelogon.c */ diff -u -r --new-file --exclude=CVS source/reply.c newsource/reply.c --- source/reply.c Tue Oct 21 12:47:18 1997 +++ newsource/reply.c Mon Oct 27 16:03:06 1997 @@ -2194,11 +2194,11 @@ mtime = make_unix_date3(inbuf+smb_vwv1); + close_file(fnum, 1); + /* try and set the date */ set_filetime(cnum,Files[fnum].name,mtime); - close_file(fnum, 1); - /* We have a cached error */ if(eclass || err) return(ERROR(eclass,err)); @@ -2242,10 +2242,10 @@ nwritten = write_file(fnum,data,numtowrite); - set_filetime(cnum,Files[fnum].name,mtime); - close_file(fnum, 1); + set_filetime(cnum,Files[fnum].name,mtime); + DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n", timestring(),fnum,cnum,numtowrite,nwritten, Connections[cnum].num_files_open)); @@ -3021,6 +3021,7 @@ int ret=0; int fnum1,fnum2; pstring dest; + struct utimbuf unix_times; pstrcpy(dest,dest1); if (target_is_directory) { @@ -3034,6 +3035,8 @@ } if (!file_exist(src,&st)) return(False); + unix_times.actime = time(NULL); + unix_times.modtime = st.st_mtime; fnum1 = find_free_file(); if (fnum1<0) return(False); @@ -3068,6 +3071,10 @@ close_file(fnum1, 0); close_file(fnum2, 0); + sys_utime(dest, &unix_times); + unix_times.actime = st.st_atime; + unix_times.modtime = st.st_mtime; + sys_utime(src, &unix_times); return(ret == st.st_size); } @@ -3147,6 +3154,16 @@ if (!has_wild) { strcat(directory,"/"); strcat(directory,mask); + + /* Ensure newname contains a '/' also */ + if(strrchr(newname,'/') == 0) { + pstring tmpstr; + + strcpy(tmpstr, "./"); + strcat(tmpstr, newname); + strcpy(newname, tmpstr); + } + if (resolve_wildcards(directory,newname) && copy_file(directory,newname,cnum,ofun, count,target_is_directory)) count++; diff -u -r --new-file --exclude=CVS source/server.c newsource/server.c --- source/server.c Tue Oct 21 18:35:51 1997 +++ newsource/server.c Mon Oct 27 16:16:53 1997 @@ -1612,13 +1612,10 @@ if (strstr(fname,".+,;=[].")) { unix_ERR_class = ERRDOS; - /* OS/2 Workplace shell fix may be main code stream in a later release. */ -#ifdef OS2_WPS_FIX - unix_ERR_code = ERRcannotopen; -#else /* OS2_WPS_FIX */ - unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; -#endif /* OS2_WPS_FIX */ - + if (get_remote_arch() != RA_OS2) + unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; /* Paranoia... */ + else + unix_ERR_code = ERRcannotopen; return; }