diff options
author | Andrew Tridgell <tridge@samba.org> | 1996-06-05 15:16:09 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1996-06-05 15:16:09 +0000 |
commit | e38afbf38210b8cf30c5b13dc5ea96a6dda433f7 (patch) | |
tree | 06281d362a0c4d1cb96713613b2f541c0dea491e | |
parent | 526cc39e432682afe57a1eb2607e1a3f261f4e8f (diff) | |
download | samba-e38afbf38210b8cf30c5b13dc5ea96a6dda433f7.tar.gz samba-e38afbf38210b8cf30c5b13dc5ea96a6dda433f7.tar.xz samba-e38afbf38210b8cf30c5b13dc5ea96a6dda433f7.zip |
- changed some debug levels in clientutil.c
- added dir_check_ftype() to clean up the file type checking a bit
- added check for libc version >= 5 for setfsuid() for Linux
- moved the AM_MASTER() and related macros to nameserv.h
- added proper defines for the various netbios announce types
- don't call the announce_backup() code, as I'm pretty sure its wrong
it sent ANN_GetBackupListReq packets as broadcasts, they are supposed
to be used only by clients to the master browser to find a list of
available backup servers to remote a netserverenum to, I don't think
nmbd should ever send one.
- fixed a bug in the browse list writing
- minor debug cleanups
- put in the code to discard our own broadcasts (it won't work for
multi-homed hosts though)
- changed ELECTION_VERSION to 1 so we can be beaten by a NT 3.51 server by
lowering the os level.
- only do sync_browse_lists() if we are the master browser, otherwise
we'll cause network overload
- don't call tell_become_backup() as it appears to be badly broken, it
should only be used when the machine being told has its MAINTAIN_LIST
to to auto. Not calling it does no great harm anyway
- fix a nasty bug where becomebackup was confused with reset browser!
- make setbuffer() not get caught by the auto protototypes
(This used to be commit cfbad9b08242962f41595273de08a7293fe432b1)
-rw-r--r-- | source3/client/clientutil.c | 36 | ||||
-rw-r--r-- | source3/include/includes.h | 2 | ||||
-rw-r--r-- | source3/include/nameserv.h | 18 | ||||
-rw-r--r-- | source3/include/proto.h | 22 | ||||
-rw-r--r-- | source3/lib/util.c | 2 | ||||
-rw-r--r-- | source3/libsmb/nmblib.c | 4 | ||||
-rw-r--r-- | source3/nameannounce.c | 155 | ||||
-rw-r--r-- | source3/namedb.c | 16 | ||||
-rw-r--r-- | source3/nameresp.c | 15 | ||||
-rw-r--r-- | source3/namework.c | 369 | ||||
-rw-r--r-- | source3/nmbd/nmbd.c | 7 | ||||
-rw-r--r-- | source3/nmbsync.c | 72 | ||||
-rw-r--r-- | source3/smbd/dir.c | 20 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 10 |
14 files changed, 368 insertions, 380 deletions
diff --git a/source3/client/clientutil.c b/source3/client/clientutil.c index e2427a40995..41c482196ad 100644 --- a/source3/client/clientutil.c +++ b/source3/client/clientutil.c @@ -216,7 +216,7 @@ BOOL cli_send_session_request(char *inbuf, char *outbuf) if (Client == -1) return False; - DEBUG(3,("Retargeted\n")); + DEBUG(5,("Retargeted\n")); set_socket_options(Client,user_socket_options); @@ -381,10 +381,10 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu } crypt_len = smb_buflen(inbuf); memcpy(cryptkey,smb_buf(inbuf),8); - DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3))); + DEBUG(5,("max mux %d\n",SVAL(inbuf,smb_vwv3))); max_vcs = SVAL(inbuf,smb_vwv4); - DEBUG(3,("max vcs %d\n",max_vcs)); - DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5))); + DEBUG(5,("max vcs %d\n",max_vcs)); + DEBUG(5,("max blk %d\n",SVAL(inbuf,smb_vwv5))); } else { /* NT protocol */ sec_mode = CVAL(inbuf,smb_vwv1); @@ -397,17 +397,17 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu memcpy(cryptkey,smb_buf(inbuf),8); if (IVAL(inbuf,smb_vwv9+1) & 1) readbraw_supported = writebraw_supported = True; - DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1))); + DEBUG(5,("max mux %d\n",SVAL(inbuf,smb_vwv1+1))); max_vcs = SVAL(inbuf,smb_vwv2+1); - DEBUG(3,("max vcs %d\n",max_vcs)); - DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1))); - DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1))); + DEBUG(5,("max vcs %d\n",max_vcs)); + DEBUG(5,("max raw %d\n",IVAL(inbuf,smb_vwv5+1))); + DEBUG(5,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1))); } - DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1))); - DEBUG(3,("max xmt %d\n",max_xmit)); - DEBUG(3,("Got %d byte crypt key\n",crypt_len)); - DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name)); + DEBUG(5,("Sec mode %d\n",SVAL(inbuf,smb_vwv1))); + DEBUG(5,("max xmt %d\n",max_xmit)); + DEBUG(5,("Got %d byte crypt key\n",crypt_len)); + DEBUG(5,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name)); doencrypt = ((sec_mode & 2) != 0); @@ -436,7 +436,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu #ifdef SMB_PASSWD if (doencrypt && *pass) { - DEBUG(3,("Using encrypted passwords\n")); + DEBUG(5,("Using encrypted passwords\n")); passlen = 24; SMBencrypt(pass,cryptkey,pword); } @@ -502,7 +502,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu SVAL(inbuf,smb_err) == ERRbadpw))) { got_pass = False; - DEBUG(3,("resending login\n")); + DEBUG(5,("resending login\n")); goto get_pass; } @@ -531,7 +531,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu /* use the returned uid from now on */ if (SVAL(inbuf,smb_uid) != uid) - DEBUG(3,("Server gave us a UID of %d. We gave %d\n", + DEBUG(5,("Server gave us a UID of %d. We gave %d\n", SVAL(inbuf,smb_uid),uid)); uid = SVAL(inbuf,smb_uid); } @@ -614,7 +614,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu cnum = SVAL(inbuf,smb_tid); - DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit)); + DEBUG(5,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit)); if (was_null) { @@ -816,7 +816,7 @@ BOOL cli_open_sockets(int port) strcpy(desthost,host); } - DEBUG(3,("Opening sockets\n")); + DEBUG(5,("Opening sockets\n")); if (*myname == 0) { @@ -841,7 +841,7 @@ BOOL cli_open_sockets(int port) if (Client == -1) return False; - DEBUG(3,("Connected\n")); + DEBUG(5,("Connected\n")); set_socket_options(Client,user_socket_options); diff --git a/source3/include/includes.h b/source3/include/includes.h index ad65bcc6075..5b29b275475 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -223,7 +223,9 @@ Here come some platform specific sections #define USE_SETSID #define HAVE_BZERO #define HAVE_MEMMOVE +#if _LINUX_C_LIB_VERSION_MAJOR >= 5 #define USE_SETFS +#endif #ifdef SHADOW_PWD #ifndef crypt #define crypt pw_encrypt diff --git a/source3/include/nameserv.h b/source3/include/nameserv.h index 51f5ec8479e..32ee625fa4f 100644 --- a/source3/include/nameserv.h +++ b/source3/include/nameserv.h @@ -22,7 +22,7 @@ /* NTAS uses 2, NT uses 1, WfWg uses 0 */ #define MAINTAIN_LIST 2 -#define ELECTION_VERSION 2 +#define ELECTION_VERSION 1 #define MAX_DGRAM_SIZE (80*18+64) #define MIN_DGRAM_SIZE 12 @@ -255,3 +255,19 @@ struct packet_struct }; +#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER) +#define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER) +#define AM_DOMCTL(work) (work->ServerType & SV_TYPE_DOMAIN_CTRL) + + +#define ANN_HostAnnouncement 1 +#define ANN_AnnouncementRequest 2 +#define ANN_Election 8 +#define ANN_GetBackupListReq 9 +#define ANN_GetBackupListResp 10 +#define ANN_BecomeBackup 11 +#define ANN_DomainAnnouncement 12 +#define ANN_MasterAnnouncement 13 +#define ANN_ResetBrowserState 14 +#define ANN_LocalMasterAnnouncement 15 + diff --git a/source3/include/proto.h b/source3/include/proto.h index face79d2558..a3f522b2740 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -51,6 +51,7 @@ BOOL dptr_fill(char *buf1,unsigned int key); BOOL dptr_zero(char *buf); void *dptr_fetch(char *buf,int *num); void *dptr_fetch_lanman2(char *params,int dptr_num); +BOOL dir_check_ftype(int cnum,int mode,struct stat *st,int dirtype); BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend); void *OpenDir(char *name); void CloseDir(void *p); @@ -99,21 +100,26 @@ int reply_sendstrt(char *inbuf,char *outbuf); int reply_sendtxt(char *inbuf,char *outbuf); int reply_sendend(char *inbuf,char *outbuf); void announce_request(struct work_record *work, struct in_addr ip); -void do_announce_request(char *info, char *to_name, int announce_type, int from, +void do_announce_request(char *info, char *to_name, int announce_type, + int from, int to, struct in_addr dest_ip); void announce_backup(void); void announce_host(void); void announce_master(void); -struct work_record *remove_workgroup(struct domain_record *d, struct work_record *work); +struct work_record *remove_workgroup(struct domain_record *d, + struct work_record *work); void expire_browse_cache(time_t t); struct work_record *find_workgroupstruct(struct domain_record *d, fstring name, BOOL add); struct domain_record *find_domain(struct in_addr source_ip); -struct domain_record *add_domain_entry(struct in_addr source_ip, struct in_addr source_mask, +struct domain_record *add_domain_entry(struct in_addr source_ip, + struct in_addr source_mask, char *name, BOOL add); struct browse_cache_record *add_browser_entry(char *name, int type, char *wg, time_t ttl, struct in_addr ip); -struct server_record *add_server_entry(struct domain_record *d, struct work_record *work, - char *name,int servertype, int ttl,char *comment, +struct server_record *add_server_entry(struct domain_record *d, + struct work_record *work, + char *name,int servertype, + int ttl,char *comment, BOOL replace); void write_browse_list(void); void expire_servers(time_t t); @@ -137,7 +143,6 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id,int rcode,int opco char *data,int len); uint16 initiate_netbios_packet(int fd,int quest_type,char *name,int name_type, int nb_flags,BOOL bcast,BOOL recurse,struct in_addr to_ip); -void send_name_reg(void); void queue_netbios_pkt_wins(int fd,int quest_type,enum cmd_type cmd, char *name,int name_type,int nb_flags, BOOL bcast,BOOL recurse,struct in_addr to_ip); @@ -162,6 +167,7 @@ struct name_record *add_netbios_entry(char *name, int type, int nb_flags, int tt void remove_name_entry(char *name,int type); void add_name_entry(char *name,int type,int nb_flags); void add_my_names(void); +void refresh_my_names(time_t t); void expire_names(time_t t); void response_name_release(struct packet_struct *p); void reply_name_release(struct packet_struct *p); @@ -174,7 +180,8 @@ void process_nmb(struct packet_struct *p); void reset_server(char *name, int state, struct in_addr ip); void tell_become_backup(void); void do_browser_lists(void); -void sync_server(enum cmd_type cmd, char *serv_name, char *work_name, int name_type, +void sync_server(enum cmd_type cmd, char *serv_name, char *work_name, + int name_type, struct in_addr ip); void update_from_reg(char *name, int type, struct in_addr ip); void add_my_domains(void); @@ -464,7 +471,6 @@ BOOL yesno(char *p); char *fgets_slash(char *s2,int maxlen,FILE *f); int set_filelen(int fd, long len); int byte_checksum(char *buf,int len); -void setbuffer(FILE *f,char *buf,int bufsize); char *dirname_dos(char *path,char *buf); void *Realloc(void *p,int size); void Abort(void ); diff --git a/source3/lib/util.c b/source3/lib/util.c index 427d15cdcfc..8c088f306e9 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -3161,7 +3161,7 @@ int byte_checksum(char *buf,int len) /**************************************************************************** this is a version of setbuffer() for those machines that only have setvbuf ****************************************************************************/ -void setbuffer(FILE *f,char *buf,int bufsize) + void setbuffer(FILE *f,char *buf,int bufsize) { setvbuf(f,buf,_IOFBF,bufsize); } diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c index 87fe5fee780..d82d89f6534 100644 --- a/source3/libsmb/nmblib.c +++ b/source3/libsmb/nmblib.c @@ -500,7 +500,7 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type) num_good_receives++; - DEBUG(4,("%s received a packet of len %d from (%s) port %d\n", + DEBUG(5,("%s received a packet of len %d from (%s) port %d\n", timestring(),length,inet_ntoa(packet->ip),packet->port)); return(packet); @@ -521,7 +521,7 @@ static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port) sock_out.sin_port = htons( port ); sock_out.sin_family = AF_INET; - DEBUG(4,("%s sending a packet of len %d to (%s) on port %d\n", + DEBUG(5,("%s sending a packet of len %d to (%s) on port %d\n", timestring(),len,inet_ntoa(ip),port)); ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out, diff --git a/source3/nameannounce.c b/source3/nameannounce.c index 083512990b4..6b086c97746 100644 --- a/source3/nameannounce.c +++ b/source3/nameannounce.c @@ -54,10 +54,6 @@ extern int workgroup_count; /* what server type are we currently */ -#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER) -#define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER) -#define AM_DOMCTL(work) (work->ServerType & SV_TYPE_DOMAIN_CTRL) - #define MSBROWSE "\001\002__MSBROWSE__\002" #define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE" @@ -73,12 +69,12 @@ void announce_request(struct work_record *work, struct in_addr ip) work->needannounce = True; - DEBUG(2,("Sending announce request to %s for workgroup %s\n", + DEBUG(2,("sending announce request to %s for workgroup %s\n", inet_ntoa(ip),work->work_group)); bzero(outbuf,sizeof(outbuf)); p = outbuf; - CVAL(p,0) = 2; /* announce request */ + CVAL(p,0) = ANN_AnnouncementRequest; p++; CVAL(p,0) = work->token; /* flags?? XXXX probably a token*/ @@ -95,7 +91,8 @@ void announce_request(struct work_record *work, struct in_addr ip) /**************************************************************************** request an announcement **************************************************************************/ -void do_announce_request(char *info, char *to_name, int announce_type, int from, +void do_announce_request(char *info, char *to_name, int announce_type, + int from, int to, struct in_addr dest_ip) { pstring outbuf; @@ -103,10 +100,10 @@ void do_announce_request(char *info, char *to_name, int announce_type, int from, bzero(outbuf,sizeof(outbuf)); p = outbuf; - CVAL(p,0) = announce_type; /* announce request */ + CVAL(p,0) = announce_type; p++; - DEBUG(2,("Sending announce type %d: info %s to %s - server %s(%x)\n", + DEBUG(2,("sending announce type %d: info %s to %s - server %s(%x)\n", announce_type, info, inet_ntoa(dest_ip),to_name,to)); StrnCpy(p,info,16); @@ -122,68 +119,66 @@ void do_announce_request(char *info, char *to_name, int announce_type, int from, **************************************************************************/ void announce_backup(void) { - static time_t lastrun = 0; - time_t t = time(NULL); - pstring outbuf; - char *p; - struct domain_record *d1; - int tok; - - if (!lastrun) lastrun = t; - if (t < lastrun + 1*60) return; - lastrun = t; - - for (tok = 0; tok <= workgroup_count; tok++) + static time_t lastrun = 0; + time_t t = time(NULL); + pstring outbuf; + char *p; + struct domain_record *d1; + int tok; + + if (!lastrun) lastrun = t; + if (t < lastrun + 1*60) return; + lastrun = t; + + for (tok = 0; tok <= workgroup_count; tok++) + { + for (d1 = domainlist; d1; d1 = d1->next) { - for (d1 = domainlist; d1; d1 = d1->next) - { - struct work_record *work; - struct domain_record *d; - - /* search for unique workgroup: only the name matters */ - for (work = d1->workgrouplist; - work && (tok != work->token); - work = work->next); + struct work_record *work; + struct domain_record *d; + + /* search for unique workgroup: only the name matters */ + for (work = d1->workgrouplist; + work && (tok != work->token); + work = work->next); + + if (!work) continue; - if (work) - { - /* found one: announce it across all domains */ - for (d = domainlist; d; d = d->next) - { - DEBUG(2,("Sending announce backup %s workgroup %s(%d)\n", - inet_ntoa(d->bcast_ip),work->work_group, - work->token)); - - bzero(outbuf,sizeof(outbuf)); - p = outbuf; - CVAL(p,0) = 9; /* backup list response */ - p++; - - CVAL(p,0) = 1; /* count? */ - SIVAL(p,1,work->token); /* workgroup unique key index */ - p += 5; - p++; - - if (AM_DOMCTL(work)) - { - send_mailslot_reply(BROWSE_MAILSLOT, - ClientDGRAM,outbuf, - PTR_DIFF(p,outbuf), - myname, work->work_group, - 0x0,0x1b,d->bcast_ip,myip); - } - else if (AM_MASTER(work)) - { - send_mailslot_reply(BROWSE_MAILSLOT, - ClientDGRAM,outbuf, - PTR_DIFF(p,outbuf), - myname, work->work_group, - 0x0,0x1d,d->bcast_ip,myip); - } - } - } - } + /* found one: announce it across all domains */ + for (d = domainlist; d; d = d->next) + { + int type=0; + + if (AM_DOMCTL(work)) { + type = 0x1b; + } else if (AM_MASTER(work)) { + type = 0x1d; + } else { + continue; + } + + DEBUG(2,("sending announce backup %s workgroup %s(%d)\n", + inet_ntoa(d->bcast_ip),work->work_group, + work->token)); + + bzero(outbuf,sizeof(outbuf)); + p = outbuf; + CVAL(p,0) = ANN_GetBackupListReq; + p++; + + CVAL(p,0) = 1; /* count? */ + SIVAL(p,1,work->token); /* workgroup unique key index */ + p += 5; + p++; + + send_mailslot_reply(BROWSE_MAILSLOT, + ClientDGRAM,outbuf, + PTR_DIFF(p,outbuf), + myname, work->work_group, + 0x0,type,d->bcast_ip,myip); + } } + } } @@ -236,9 +231,6 @@ void announce_host(void) work->lastannounce_time = t; - DEBUG(2,("Sending announcement to subnet %s for workgroup %s\n", - inet_ntoa(d->bcast_ip),work->work_group)); - if (!ip_equal(bcast_ip,d->bcast_ip)) { stype &= ~(SV_TYPE_POTENTIAL_BROWSER | SV_TYPE_MASTER_BROWSER | SV_TYPE_DOMAIN_MASTER | SV_TYPE_BACKUP_BROWSER | @@ -258,7 +250,8 @@ void announce_host(void) p = outbuf+1; CVAL(p,0) = updatecount; - SIVAL(p,1,work->announce_interval*1000); /* ms - despite the spec */ + /* ms - despite the spec */ + SIVAL(p,1,work->announce_interval*1000); namep = p+5; StrnCpy(namep,my_name,16); strupper(namep); @@ -279,14 +272,20 @@ void announce_host(void) { SIVAL(stypep,0,work->ServerType); - CVAL(outbuf,0) = 15; /* local member announce */ + DEBUG(2,("sending local master announce to %s for %s\n", + inet_ntoa(d->bcast_ip),work->work_group)); + + CVAL(outbuf,0) = ANN_LocalMasterAnnouncement; send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, PTR_DIFF(p,outbuf), my_name,work->work_group,0, 0x1e,d->bcast_ip,myip); - CVAL(outbuf,0) = 12; /* domain announce */ + DEBUG(2,("sending domain announce to %s for %s\n", + inet_ntoa(d->bcast_ip),work->work_group)); + + CVAL(outbuf,0) = ANN_DomainAnnouncement; StrnCpy(namep,work->work_group,15); strupper(namep); @@ -302,11 +301,15 @@ void announce_host(void) } else { - CVAL(outbuf,0) = 1; /* host announce */ + DEBUG(2,("sending host announce to %s for %s\n", + inet_ntoa(d->bcast_ip),work->work_group)); + + CVAL(outbuf,0) = ANN_HostAnnouncement; send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, PTR_DIFF(p,outbuf), - my_name,work->work_group,0,0x1d,d->bcast_ip,myip); + my_name,work->work_group,0,0x1d, + d->bcast_ip,myip); } } } diff --git a/source3/namedb.c b/source3/namedb.c index 3e19f3fc8a3..fc14c4d5c60 100644 --- a/source3/namedb.c +++ b/source3/namedb.c @@ -177,7 +177,8 @@ static void remove_old_servers(struct work_record *work, time_t t) /******************************************************************* remove workgroups ******************************************************************/ -struct work_record *remove_workgroup(struct domain_record *d, struct work_record *work) +struct work_record *remove_workgroup(struct domain_record *d, + struct work_record *work) { struct work_record *ret_work = NULL; @@ -388,19 +389,18 @@ static void dump_workgroups(void) { struct work_record *work; - DEBUG(3,("dump domain %15s: ", inet_ntoa(d->bcast_ip))); - DEBUG(3,(" %15s:\n", inet_ntoa(d->bcast_ip))); + DEBUG(4,("dump domain bcast=%15s: ", inet_ntoa(d->bcast_ip))); + DEBUG(4,(" netmask=%15s:\n", inet_ntoa(d->mask_ip))); for (work = d->workgrouplist; work; work = work->next) { + DEBUG(4,("\t%s(%d)\n", work->work_group, work->token)); if (work->serverlist) { - struct server_record *s; - - DEBUG(3,("\t%s(%d)\n", work->work_group, work->token)); + struct server_record *s; for (s = work->serverlist; s; s = s->next) { - DEBUG(3,("\t\t%s %8x (%s)\n", + DEBUG(4,("\t\t%s %8x (%s)\n", s->serv.name, s->serv.type, s->serv.comment)); } } @@ -674,7 +674,7 @@ void write_browse_list(void) sprintf(tmp, "\"%s\"", s->serv.name); fprintf(f, "%-25s ", tmp); fprintf(f, "%08x ", s->serv.type); - sprintf(tmp, "\"%s\"", s->serv.comment); + sprintf(tmp, "\"%s\" ", s->serv.comment); fprintf(f, "%-30s", tmp); fprintf(f, "\"%s\"\n", work->work_group); } diff --git a/source3/nameresp.c b/source3/nameresp.c index 8ed2ba92c43..435864a7843 100644 --- a/source3/nameresp.c +++ b/source3/nameresp.c @@ -174,7 +174,8 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id,int rcode,int opco initiate a netbios packet ****************************************************************************/ uint16 initiate_netbios_packet(int fd,int quest_type,char *name,int name_type, - int nb_flags,BOOL bcast,BOOL recurse,struct in_addr to_ip) + int nb_flags,BOOL bcast,BOOL recurse, + struct in_addr to_ip) { struct packet_struct p; struct nmb_packet *nmb = &p.packet.nmb; @@ -432,13 +433,11 @@ void listen_for_packets(BOOL run_election) { struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET); if (packet) { -#if 0 +#if 1 if (ip_equal(packet->ip,myip) && (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) { - DEBUG(3,("discarding packet from %s:%d\n", + DEBUG(5,("discarding own packet from %s:%d\n", inet_ntoa(packet->ip),packet->port)); - DEBUG(3,("myip=%s eq=%d\n", - inet_ntoa(myip),ip_equal(packet->ip,myip))); free_packet(packet); } else #endif @@ -452,13 +451,11 @@ void listen_for_packets(BOOL run_election) { struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET); if (packet) { -#if 0 +#if 1 if (ip_equal(packet->ip,myip) && (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) { - DEBUG(3,("discarding packet from %s:%d\n", + DEBUG(5,("discarding own packet from %s:%d\n", inet_ntoa(packet->ip),packet->port)); - DEBUG(3,("myip=%s eq=%d\n", - inet_ntoa(myip),ip_equal(packet->ip,myip))); free_packet(packet); } else #endif diff --git a/source3/namework.c b/source3/namework.c index ee60e9115f3..9697be23ef6 100644 --- a/source3/namework.c +++ b/source3/namework.c @@ -85,73 +85,76 @@ state - 0x01 become backup instead of master **************************************************************************/ void reset_server(char *name, int state, struct in_addr ip) { - char outbuf[20]; - char *p; + char outbuf[20]; + char *p; - bzero(outbuf,sizeof(outbuf)); - p = outbuf; + bzero(outbuf,sizeof(outbuf)); + p = outbuf; - CVAL(p,0) = 14; /* request reset browser state */ - CVAL(p,2) = state; /* type of request */ - p += 2; + CVAL(p,0) = ANN_ResetBrowserState; + CVAL(p,2) = state; + p += 2; - send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), - myname,name,0x20,0x1d,ip,myip); + DEBUG(2,("sending reset to %s %s of state %d\n", + name,inet_ntoa(ip),state)); + + send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), + myname,name,0x20,0x1d,ip,myip); } + /**************************************************************************** tell a server to become a backup browser **************************************************************************/ void tell_become_backup(void) { - struct domain_record *d; - for (d = domainlist; d; d = d->next) + struct domain_record *d; + for (d = domainlist; d; d = d->next) + { + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) + struct server_record *s; + int num_servers = 0; + int num_backups = 0; + + for (s = work->serverlist; s; s = s->next) + { + if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; + + num_servers++; + + if (strequal(myname, s->serv.name)) continue; + + if (s->serv.type & SV_TYPE_BACKUP_BROWSER) { + num_backups++; + continue; + } + + if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue; + + if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue; + + DEBUG(3,("num servers: %d num backups: %d\n", + num_servers, num_backups)); + + /* make first server a backup server. thereafter make every + tenth server a backup server */ + if (num_backups != 0 && (num_servers+9) / num_backups > 10) { - struct server_record *s; - int num_servers = 0; - int num_backups = 0; - - for (s = work->serverlist; s; s = s->next) - { - if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; - - num_servers++; - - if (strequal(myname, s->serv.name)) continue; - - if (s->serv.type & SV_TYPE_BACKUP_BROWSER) - { - num_backups++; - continue; - } - - if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue; - - if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue; - - DEBUG(3,("num servers: %d num backups: %d\n", - num_servers, num_backups)); - - /* make first server a backup server. thereafter make every - tenth server a backup server */ - if (num_backups != 0 && (num_servers+9) / num_backups > 10) - { - continue; - } - - DEBUG(3,("workgroup %s subnet %s: make backup: %s %8x \n", - work->work_group, inet_ntoa(d->bcast_ip), - s->serv.name, s->serv.type)); - - /* type 11 request from MYNAME(20) to WG(1e) for SERVER */ - do_announce_request(s->serv.name, work->work_group, - 11, 0x20, 0x1e, d->bcast_ip); - } + continue; } + + DEBUG(2,("sending become backup to %s %s for %s\n", + s->serv.name, inet_ntoa(d->bcast_ip), + work->work_group)); + + /* type 11 request from MYNAME(20) to WG(1e) for SERVER */ + do_announce_request(s->serv.name, work->work_group, + ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip); + } } + } } /**************************************************************************** @@ -159,22 +162,26 @@ find a server responsible for a workgroup, and sync browse lists **************************************************************************/ static BOOL sync_browse_entry(struct browse_cache_record *b) { - struct domain_record *d; - struct work_record *work; -/* - if (!strequal(serv_name, b->name)) - { - DEBUG(0, ("browser's netbios name (%s) does not match %s (%s)", - b->name, inet_ntoa(b->ip), serv_name)); - } -*/ - if (!(d = find_domain(b->ip))) return False; - if (!(work = find_workgroupstruct(d, b->group, False))) return False; - - sync_browse_lists(work,b->name,0x20,b->ip); - b->synced = True; - - return True; + struct domain_record *d; + struct work_record *work; + /* + if (!strequal(serv_name, b->name)) + { + DEBUG(0, ("browser's netbios name (%s) does not match %s (%s)", + b->name, inet_ntoa(b->ip), serv_name)); + } + */ + if (!(d = find_domain(b->ip))) return False; + if (!(work = find_workgroupstruct(d, b->group, False))) return False; + + if (AM_MASTER(work)) { + /* only try to sync browse lists if we are the master, otherwise + the net could get a little bit too busy */ + sync_browse_lists(work,b->name,0x20,b->ip); + } + b->synced = True; + + return True; } @@ -183,26 +190,26 @@ search through browser list for an entry to sync with **************************************************************************/ void do_browser_lists(void) { - struct browse_cache_record *b; - static time_t last = 0; - time_t t = time(NULL); - - if (t-last < 4) return; /* don't do too many of these at once! */ - - last = t; - - /* pick any entry in the list, preferably one whose time is up */ - for (b = browserlist; b && b->next; b = b->next) - { - if (b->sync_time < t && b->synced == False) break; - } - - if (!b || b->synced || sync_browse_entry(b)) - { - /* leave entries (even ones already sync'd) for up to a minute. - this stops them getting re-sync'd too often */ - expire_browse_cache(t - 60); - } + struct browse_cache_record *b; + static time_t last = 0; + time_t t = time(NULL); + + if (t-last < 4) return; /* don't do too many of these at once! */ + + last = t; + + /* pick any entry in the list, preferably one whose time is up */ + for (b = browserlist; b && b->next; b = b->next) + { + if (b->sync_time < t && b->synced == False) break; + } + + if (!b || b->synced || sync_browse_entry(b)) + { + /* leave entries (even ones already sync'd) for up to a minute. + this stops them getting re-sync'd too often */ + expire_browse_cache(t - 60); + } } @@ -210,16 +217,18 @@ void do_browser_lists(void) find a server responsible for a workgroup, and sync browse lists control ends up back here via response_name_query. **************************************************************************/ -void sync_server(enum cmd_type cmd, char *serv_name, char *work_name, int name_type, +void sync_server(enum cmd_type cmd, char *serv_name, char *work_name, + int name_type, struct in_addr ip) { - add_browser_entry(serv_name, name_type, work_name, 0, ip); + add_browser_entry(serv_name, name_type, work_name, 0, ip); - if (cmd == MASTER_SERVER_CHECK) - { - /* announce ourselves as a master browser to serv_name */ - do_announce_request(myname, serv_name, 13, 0x20, 0, ip); - } + if (cmd == MASTER_SERVER_CHECK) + { + /* announce ourselves as a master browser to serv_name */ + do_announce_request(myname, serv_name, ANN_MasterAnnouncement, + 0x20, 0, ip); + } } @@ -230,7 +239,7 @@ void update_from_reg(char *name, int type, struct in_addr ip) { /* default server type: minimum guess at requirement XXXX */ - DEBUG(4,("update from registration: host %s ip %s type %0x\n", + DEBUG(3,("update from registration: host %s ip %s type %0x\n", name, inet_ntoa(ip), type)); /* workgroup types, but not a chat type */ @@ -286,7 +295,7 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name, int i, j; char *theirname = src_name->name; - DEBUG(3,("Backup list of %s to %s: %s(%x) %s(%x)\n", + DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n", work_name, inet_ntoa(ip), myname,0x20,theirname,0x0)); @@ -467,36 +476,35 @@ static void process_announce(struct packet_struct *p,int command,char *buf) comment[43] = 0; - DEBUG(3,("Announce(%d) %s(%x)",command,name,name[15])); - DEBUG(3,("%s count=%d ttl=%d OS=(%d,%d) type=%08x comment=%s\n", + DEBUG(4,("Announce(%d) %s(%x)",command,name,name[15])); + DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x comment=%s\n", namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor, servertype,comment)); name[15] = 0; - if (dgram->dest_name.name_type == 0 && command == 1) + if (dgram->dest_name.name_type == 0 && command == ANN_HostAnnouncement) { DEBUG(2,("Announce to nametype(0) not supported yet\n")); return; } - if (command == 12 && ((!strequal(dgram->dest_name.name, MSBROWSE)) || - dgram->dest_name.name_type != 0x1)) + + if (command == ANN_DomainAnnouncement && + ((!strequal(dgram->dest_name.name, MSBROWSE)) || + dgram->dest_name.name_type != 0x1)) { - DEBUG(0, ("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n", + DEBUG(0,("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n", command, inet_ntoa(ip), namestr(&dgram->dest_name))); return; } if (same_context(dgram)) return; - if (command == 12) - { - work_name = name; - } - else - { - work_name = dgram->dest_name.name; - } + if (command == ANN_DomainAnnouncement) { + work_name = name; + } else { + work_name = dgram->dest_name.name; + } if (!(work = find_workgroupstruct(d, work_name, False))) return; @@ -507,9 +515,12 @@ static void process_announce(struct packet_struct *p,int command,char *buf) /* add them to our browse list */ add_server_entry(d,work,name,servertype,ttl,comment,True); - /* make a selection of machines become backup browsers (1 in 10) */ +#if 0 + /* the tell become backup code is broken, no great harm is done by + disabling it */ tell_become_backup(); - +#endif + /* get their browse list from them and add it to ours. */ add_browser_entry(serv_name,dgram->dest_name.name_type, work->work_group,30,ip); @@ -575,8 +586,8 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf) struct in_addr back_ip; struct domain_record *d; - DEBUG(4, ("Searching for backup browser %s at %s...\n", - buf1, inet_ntoa(ip))); + DEBUG(4,("Searching for backup browser %s at %s...\n", + buf1, inet_ntoa(ip))); /* XXXX assume name is a DNS name NOT a netbios name. a more complete approach is to use reply_name_query functionality to find the name */ @@ -635,18 +646,15 @@ static void process_send_backup_list(struct packet_struct *p,char *buf) int info = SVAL(buf,3); /* XXXX don't know: some sort of info */ int name_type = dgram->dest_name.name_type; - DEBUG(0,("Send Backup request to %s token=%d info = %x count=%d\n", - namestr(&dgram->dest_name), token, info, count)); - if (same_context(dgram)) return; if (count <= 0) return; - if (name_type != 0x1b && name_type != 0x1d) - { - DEBUG(0, ("backup request to wrong type %d\n", name_type)); - return; - } + if (name_type != 0x1b && name_type != 0x1d) { + DEBUG(0,("backup request to wrong type %d from %s\n", + name_type,inet_ntoa(ip))); + return; + } for (d = domainlist; d; d = d->next) { @@ -654,8 +662,9 @@ static void process_send_backup_list(struct packet_struct *p,char *buf) { if (strequal(work->work_group, dgram->dest_name.name)) { - DEBUG(3, ("found workgroup %s(%d)\n", - work->work_group, work->token)); + DEBUG(2,("sending backup list to %s %s count=%d\n", + namestr(&dgram->dest_name),inet_ntoa(ip),count)); + send_backup_list(work->work_group,&dgram->source_name, count,token,info,name_type,ip); return; @@ -679,7 +688,7 @@ static void process_reset_browser(struct packet_struct *p,char *buf) struct dgram_packet *dgram = &p->packet.dgram; int state = CVAL(buf,0); - DEBUG(1,("Diagnostic browser reset request to %s state=0x%X\n", + DEBUG(1,("received diagnostic browser reset request to %s state=0x%X\n", namestr(&dgram->dest_name), state)); /* stop being a master but still deal with being a backup browser */ @@ -714,7 +723,7 @@ static void process_reset_browser(struct packet_struct *p,char *buf) /* stop browsing altogether. i don't think this is a good idea! */ if (state & 0x4) { - DEBUG(1, ("ignoring request to stop being a browser. sorry!\n")); + DEBUG(1,("ignoring request to stop being a browser. sorry!\n")); } } @@ -850,49 +859,49 @@ BOOL listening_type(struct packet_struct *p, int command) switch (command) { - case 1: /* host announce */ + case ANN_HostAnnouncement: { if (type != 0x0 || type != 0x20) return (False); break; } - case 2: /* announce request */ + case ANN_AnnouncementRequest: { return (True); break; } - case 8: /* election */ + case ANN_Election: { return (True); break; } - case 9: /* get backup list */ + case ANN_GetBackupListReq: { return (True); break; } - case 10: /* receive backup list */ + case ANN_GetBackupListResp: { return (True); break; } - case 12: /* domain announce */ + case ANN_DomainAnnouncement: { if (type != 0x1b || type != 0x1c) return (False); break; } - case 13: /* master announcement */ + case ANN_MasterAnnouncement: { if (type != 0x1d) return (False); break; } - case 15: /* local master announce */ + case ANN_LocalMasterAnnouncement: { if (type != 0x1c || type != 0x1d) return (False); break; @@ -910,119 +919,57 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len) int command = CVAL(buf,0); switch (command) { - case 1: /* host announce */ - case 12: /* domain announce */ - case 15: /* local master announce */ + case ANN_HostAnnouncement: + case ANN_DomainAnnouncement: + case ANN_LocalMasterAnnouncement: { process_announce(p,command,buf+1); break; } - case 2: /* announce request */ + case ANN_AnnouncementRequest: { process_announce_request(p,buf+1); break; } - case 8: /* election */ + case ANN_Election: { process_election(p,buf+1); break; } - case 9: /* get backup list */ + case ANN_GetBackupListReq: { process_send_backup_list(p,buf+1); break; } - case 10: /* receive backup list */ + case ANN_GetBackupListResp: { -#ifdef TEST_CODE - struct dgram_packet *dgram = &p->packet.dgram; - int i, j; - - DEBUG(4, ("ignoring browse packet %d from %s %s to %s\n", - command, namestr(&dgram->source_name), - inet_ntoa(p->ip), namestr(&dgram->dest_name))); - - for (i = 0; i < len; i+= 16) - { - DEBUG(4, ("%3x char ", i)); - - for (j = 0; j < 16; j++) - { - unsigned char x = buf[i+j]; - if (x < 32 || x > 127) x = '.'; - - if (i+j >= len) break; - DEBUG(4, ("%c", x)); - } - - DEBUG(4, (" hex ", i)); - - for (j = 0; j < 16; j++) - { - if (i+j >= len) break; - DEBUG(4, (" %02x", buf[i+j])); - } - - DEBUG(4, ("\n")); - } - -#endif /* TEST_CODE */ process_rcv_backup_list(p, buf+1); break; } - case 11: /* reset browser state */ + case ANN_ResetBrowserState: { process_reset_browser(p, buf+1); break; } - case 13: /* master announcement */ + case ANN_MasterAnnouncement: { process_master_announce(p,buf+1); break; } -#ifdef TEST_CODE default: { struct dgram_packet *dgram = &p->packet.dgram; - int i, j; - - DEBUG(4, ("ignoring browse packet %d from %s %s to %s\n", - command, namestr(&dgram->source_name), - inet_ntoa(p->ip), namestr(&dgram->dest_name))); - - for (i = 0; i < len; i+= 16) - { - DEBUG(4, ("%3x char ", i)); - - for (j = 0; j < 16; j++) - { - unsigned char x = buf[i+j]; - if (x < 32 || x > 127) x = '.'; - - if (i+j >= len) break; - DEBUG(4, ("%c", x)); - } - - DEBUG(4, (" hex ", i)); - - for (j = 0; j < 16; j++) - { - if (i+j >= len) break; - DEBUG(4, (" %02x", buf[i+j])); - } - - DEBUG(4, ("\n")); - } - + DEBUG(4,("ignoring browse packet %d from %s %s to %s\n", + command, namestr(&dgram->source_name), + inet_ntoa(p->ip), namestr(&dgram->dest_name))); } -#endif /* TEST_CODE */ } } @@ -1053,7 +1000,7 @@ void process_dgram(struct packet_struct *p) len = SVAL(buf,smb_vwv11); buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); - DEBUG(3,("datagram from %s to %s for %s of type %d len=%d\n", + DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n", namestr(&dgram->source_name),namestr(&dgram->dest_name), smb_buf(buf),CVAL(buf2,0),len)); diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index b6ef717cc0a..a977667c2e2 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -293,7 +293,14 @@ static void process(void) run_elections(); announce_host(); + +#if 0 + /* what was this stuff supposed to do? It sent + ANN_GetBackupListReq packets which I think should only be + sent when trying to find out who to browse with */ announce_backup(); +#endif + announce_master(); expire_names_and_servers(); diff --git a/source3/nmbsync.c b/source3/nmbsync.c index c3e3f43e517..7e8cdd67e15 100644 --- a/source3/nmbsync.c +++ b/source3/nmbsync.c @@ -142,42 +142,42 @@ static BOOL add_info(struct domain_record *d, struct work_record *work, int serv void sync_browse_lists(struct work_record *work, char *name, int nm_type, struct in_addr ip) { - struct domain_record *d; - pid = getpid(); - uid = getuid(); - gid = getgid(); - mid = pid + 100; - name_type = nm_type; - - got_pass = True; - - DEBUG(4, ("sync browse lists with %s for %s %s\n", - work->work_group, name, inet_ntoa(ip))); - - strcpy(workgroup,work->work_group); - strcpy(desthost,name); - dest_ip = ip; - - if (zero_ip(dest_ip)) return; - have_ip = True; - - if (!(d = find_domain(ip))) return; - - connect_as_ipc = True; - - /* connect as server and get domains, then servers */ - - sprintf(service,"\\\\%s\\IPC$", name); - strupper(service); - - if (cli_open_sockets(SMB_PORT)) + struct domain_record *d; + pid = getpid(); + uid = getuid(); + gid = getgid(); + mid = pid + 100; + name_type = nm_type; + + got_pass = True; + + DEBUG(4,("sync browse lists with %s for %s %s\n", + work->work_group, name, inet_ntoa(ip))); + + strcpy(workgroup,work->work_group); + strcpy(desthost,name); + dest_ip = ip; + + if (zero_ip(dest_ip)) return; + have_ip = True; + + if (!(d = find_domain(ip))) return; + + connect_as_ipc = True; + + /* connect as server and get domains, then servers */ + + sprintf(service,"\\\\%s\\IPC$", name); + strupper(service); + + if (cli_open_sockets(SMB_PORT)) + { + if (cli_send_login(NULL,NULL,True,True)) { - if (cli_send_login(NULL,NULL,True,True)) - { - add_info(d, work, SV_TYPE_DOMAIN_ENUM); - add_info(d, work, SV_TYPE_ALL&~SV_TYPE_DOMAIN_ENUM); - } - - close_sockets(); + add_info(d, work, SV_TYPE_DOMAIN_ENUM); + add_info(d, work, SV_TYPE_ALL&~SV_TYPE_DOMAIN_ENUM); } + + close_sockets(); + } } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 214b28dad04..32f2eb5e7de 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -412,6 +412,16 @@ void *dptr_fetch_lanman2(char *params,int dptr_num) } /**************************************************************************** +check a filetype for being valid +****************************************************************************/ +BOOL dir_check_ftype(int cnum,int mode,struct stat *st,int dirtype) +{ + if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) + return False; + return True; +} + +/**************************************************************************** get a directory entry ****************************************************************************/ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend) @@ -474,11 +484,11 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo *mode = dos_mode(cnum,pathreal,&sbuf); - if (((*mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) - { - DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); - continue; - } + if (!dir_check_ftype(cnum,*mode,&sbuf,dirtype)) { + DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); + continue; + } + *size = sbuf.st_size; *date = sbuf.st_mtime; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 36dd5eba3e4..60e9ae2b294 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -325,11 +325,11 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l mode = dos_mode(cnum,pathreal,&sbuf); - if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) - { - DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); - continue; - } + if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) { + DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); + continue; + } + size = sbuf.st_size; mdate = sbuf.st_mtime; adate = sbuf.st_atime; |