From - Fri Nov 26 14:59:09 1999 Message-Id: <199911260555.QAA17009@smtp.sw.oz.au> Errors-To: listproc-errors@samba.anu.edu.au Originator: samba-technical@samba.org Sender: samba-technical@samba.org Precedence: bulk From: lists-samba-technical@aurema.com To: Multiple recipients of list SAMBA-TECHNICAL Subject: Patches to add information and improve readability for smbstatus/swat X-Listprocessor-Version: 6.0d -- ListProcessor by Anastasios Kotsikonas X-URL: http://lists.samba.org/ X-Comment: developer discussion of Samba implementation X-Mailer: ELM [version 2.4 PL24 PGP3 *ALPHA*] Date: Fri, 26 Nov 1999 16:56:58 +1100 Content-Type: text The following is a Samba2.0.6 update of a patch I first did for Samba1. It adds a reference to the connection number (cnum) into the oplock record so that the session responsible for the lock can also be identified. This means that smbstatus -u will only print oplocks associated with the user specified. I have also tidied up the print format for the smbstatus and swat reports to make it more concise and useful - the oplock time is reported as a difference between the time the lock was acquired and the current time. The patch also speeds up swat by cacheing the session records instead of re-reading them from the file about 4 times - it may make sense to sort the list according to some argument - by user, share, time etc. What should probably be done is to add the equivalent of smbstatus -u to the swat status page to allow info on a single or set of selected users. I haven't spent enough time working out how the http stuff works to build the web glue for that. The reporting stuff would be easy.. Hope this finds favour, Regards Chris -- Chris Maltby -Aurema Pty Limited- (formerly Softway) - chris@sw.oz.au PHONE: +61-2-9698-2322 "In most companies the Managing Director has FAX: +61-2-9699-9174 his office in the future." _- Mark V. Shaney *** source/web/statuspage.c.orig Wed Oct 13 15:27:03 1999 --- source/web/statuspage.c Mon Nov 15 16:38:16 1999 *************** *** 21,38 **** #include "includes.h" ! static char *tstring(time_t t) { static pstring buf; ! pstrcpy(buf, asctime(LocalTime(&t))); all_string_sub(buf," "," ",sizeof(buf)); return buf; } static void print_share_mode(share_mode_entry *e, char *fname) { ! printf("%d",(int)e->pid); printf(""); switch ((e->share_mode>>4)&0xF) { case DENY_NONE: printf("DENY_NONE"); break; --- 21,76 ---- #include "includes.h" + #define talloc(t) ((t *) malloc(sizeof (t))) ! struct session_record ! { ! struct session_record *next; ! struct connect_record crec; ! } *srecs; ! ! struct timeval now; ! ! static char *timediff(time_t t) { static pstring buf; ! ! if (t < (60*60)) ! snprintf(buf, sizeof(buf), "%2ldm%02lds", t/60, t%60); ! else if ((t = (t+30)/60) < (24*60)) ! snprintf(buf, sizeof(buf), "%2ldh%02ldm", t/60, t%60); ! else if ((t = (t+30)/60) < (7*24)) ! snprintf(buf, sizeof(buf), "%2ldd%02ldh", t/24, t%24); ! else ! snprintf(buf, sizeof(buf), "%2ldw%02ldd", t/(7*24), (t/24)%7); ! all_string_sub(buf," "," ",sizeof(buf)); ! return buf; ! } ! ! static char *tstring(time_t *t) ! { ! static pstring buf; ! struct tm *tm = LocalTime(t); ! ! #ifdef HAVE_STRFTIME ! strftime(buf, sizeof(buf), "%Y/%m/%d %H:%M:%S%n", tm); ! #else ! pstrcpy(buf, asctime(tm)); ! #endif all_string_sub(buf," "," ",sizeof(buf)); return buf; } static void print_share_mode(share_mode_entry *e, char *fname) { ! struct session_record *p; ! ! for (p = srecs; p != NULL; p = p->next) { ! if (p->crec.pid == e->pid && p->crec.cnum == e->cnum) ! break; ! } ! printf("%s", p != NULL ? uidtoname(p->crec.uid) : ""); ! printf("%d",(int)e->pid); printf(""); switch ((e->share_mode>>4)&0xF) { case DENY_NONE: printf("DENY_NONE"); break; *************** *** 45,53 **** printf(""); switch (e->share_mode&0xF) { ! case 0: printf("RDONLY "); break; ! case 1: printf("WRONLY "); break; ! case 2: printf("RDWR "); break; } printf(""); --- 83,91 ---- printf(""); switch (e->share_mode&0xF) { ! case 0: printf("R/-"); break; ! case 1: printf("-/W"); break; ! case 2: printf("R/W"); break; } printf(""); *************** *** 55,80 **** if((e->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) ! printf("EXCLUSIVE+BATCH "); else if (e->op_type & EXCLUSIVE_OPLOCK) ! printf("EXCLUSIVE "); else if (e->op_type & BATCH_OPLOCK) ! printf("BATCH "); else if (e->op_type & LEVEL_II_OPLOCK) ! printf("LEVEL_II "); else ! printf("NONE "); printf(""); printf("%s%s\n", ! dos_to_unix(fname,False),tstring(e->time.tv_sec)); } /* show the current server status */ void status_page(void) { ! struct connect_record crec; pstring fname; FILE *f; char *v; --- 93,119 ---- if((e->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) ! printf("EXCL+BATCH"); else if (e->op_type & EXCLUSIVE_OPLOCK) ! printf("EXCL"); else if (e->op_type & BATCH_OPLOCK) ! printf("BATCH"); else if (e->op_type & LEVEL_II_OPLOCK) ! printf("LEVEL_II"); else ! printf("NONE"); printf(""); + printf("%s", p != NULL ? p->crec.name : ""); printf("%s%s\n", ! dos_to_unix(fname,False),timediff(now.tv_sec - e->time.tv_sec)); } /* show the current server status */ void status_page(void) { ! struct session_record *p; pstring fname; FILE *f; char *v; *************** *** 126,145 **** pstrcat(fname,"/STATUS..LCK"); ! f = sys_fopen(fname,"r"); ! if (f) { ! while (!feof(f)) { ! if (fread(&crec,sizeof(crec),1,f) != 1) break; ! if (crec.magic == 0x280267 && crec.cnum == -1 && ! process_exists(crec.pid)) { ! char buf[30]; ! slprintf(buf,sizeof(buf)-1,"kill_%d", (int)crec.pid); ! if (cgi_variable(buf)) { ! kill_pid(crec.pid); ! } ! } } ! fclose(f); } printf("

Server Status

\n"); --- 165,202 ---- pstrcat(fname,"/STATUS..LCK"); ! if ((f = sys_fopen(fname,"r")) != NULL) { ! struct session_record **op = &srecs; ! ! p = NULL; ! while (!feof(f)) { ! if (p == NULL && (p = talloc(struct session_record)) == NULL) ! break; ! if (fread(&p->crec,sizeof(p->crec),1,f) != 1) ! break; ! if (p->crec.magic != 0x280267 || !process_exists(p->crec.pid)) ! continue; ! *op = p; ! op = &p->next; ! p = NULL; ! } ! *op = NULL; ! fclose(f); ! } else { ! printf("Couldn't open status file %s\n",fname); ! if (!lp_status(-1)) ! printf("You need to have status=yes in your smb config file\n"); ! } ! ! for (p = srecs; p != NULL; p = p->next) { ! if (p->crec.magic == 0x280267 && p->crec.cnum == -1) { ! char buf[30]; ! ! slprintf(buf,sizeof(buf)-1,"kill_%d", (int)(p->crec.pid)); ! if (cgi_variable(buf)) { ! kill_pid(p->crec.pid); } ! } } printf("

Server Status

\n"); *************** *** 159,172 **** printf("

\n"); ! f = sys_fopen(fname,"r"); ! if (!f) { ! /* open failure either means no connections have been ! made or status=no */ ! if (!lp_status(-1)) ! printf("You need to have status=yes in your smb config file\n"); ! } ! printf("\n"); --- 216,222 ---- printf("

\n"); ! fflush(stdout); printf("

\n"); *************** *** 207,263 **** } printf("\n"); ! while (f && !feof(f)) { ! if (fread(&crec,sizeof(crec),1,f) != 1) ! break; ! if (crec.magic == 0x280267 && ! crec.cnum == -1 && ! process_exists(crec.pid)) { ! printf("\n", ! (int)crec.pid, ! crec.machine,crec.addr, ! tstring(crec.start)); ! if (geteuid() == 0) { ! printf("\n", ! (int)crec.pid); ! } ! printf("\n"); } } printf("
%d%s%s%s

\n"); - - if (f) fseek(f, 0, SEEK_SET); printf("

Active Shares

\n"); printf("\n"); printf("\n\n"); ! while (f && !feof(f)) { ! if (fread(&crec,sizeof(crec),1,f) != 1) ! break; ! if (crec.cnum == -1) continue; ! if (crec.magic == 0x280267 && process_exists(crec.pid)) { ! printf("\n", ! crec.name,uidtoname(crec.uid), ! gidtoname(crec.gid),(int)crec.pid, ! crec.machine, ! tstring(crec.start)); ! } } printf("
ShareUserGroupPIDClientDate
%s%s%s%d%s%s

\n"); printf("

Open Files

\n"); printf("\n"); ! printf("\n"); locking_init(1); share_mode_forall(print_share_mode); locking_end(); printf("
PIDSharingR/WOplockFileDate
\n"); ! ! if (f) fclose(f); printf("\n"); --- 257,308 ---- } printf("\n"); ! for (p = srecs; p != NULL; p = p->next) { ! if (p->crec.magic == 0x280267 && p->crec.cnum == -1) { ! printf("%d%s%s%s\n", ! (int)p->crec.pid, ! p->crec.machine,p->crec.addr, ! tstring(&p->crec.start)); ! if (geteuid() == 0) { ! printf("\n", ! (int)p->crec.pid); } + printf("\n"); + } } printf("

\n"); printf("

Active Shares

\n"); printf("\n"); printf("\n\n"); ! for (p = srecs; p != NULL; p = p->next) { ! if (p->crec.magic != 0x280267 || p->crec.cnum == -1) continue; ! printf("\n", ! p->crec.name,uidtoname(p->crec.uid), ! gidtoname(p->crec.gid),(int)p->crec.pid, ! p->crec.machine, ! tstring(&p->crec.start)); } printf("
ShareUserGroupPIDClientDate
%s%s%s%d%s%s

\n"); + #ifdef HAVE_GETTIMEOFDAY_TZ + gettimeofday(&now,NULL); + #else + gettimeofday(&now); + #endif + printf("

Open Files

\n"); printf("\n"); ! printf("\n"); locking_init(1); share_mode_forall(print_share_mode); locking_end(); printf("
UserPIDSharingR/WOplockShareFileHeld
\n"); ! fflush(stdout); printf("\n"); *** source/locking/locking_shm.c.orig Wed Jul 21 11:25:10 1999 --- source/locking/locking_shm.c Fri Nov 12 18:12:39 1999 *************** *** 220,225 **** --- 220,226 ---- created it still exists. Copy it into the output array. */ share_array[num_entries_copied].pid = entry_scanner_p->e.pid; + share_array[num_entries_copied].cnum = entry_scanner_p->e.cnum; share_array[num_entries_copied].share_mode = entry_scanner_p->e.share_mode; share_array[num_entries_copied].op_port = entry_scanner_p->e.op_port; share_array[num_entries_copied].op_type = entry_scanner_p->e.op_type; *************** *** 471,476 **** --- 472,478 ---- new_entry_p = shmops->offset2addr(new_entry_offset); new_entry_p->e.pid = getpid(); + new_entry_p->e.cnum = fsp->conn->cnum; new_entry_p->e.share_mode = fsp->share_mode; new_entry_p->e.op_port = port; new_entry_p->e.op_type = op_type; *** source/locking/locking_slow.c.orig Wed Oct 13 15:26:51 1999 --- source/locking/locking_slow.c Fri Nov 12 18:12:39 1999 *************** *** 46,52 **** #define SMF_FILENAME_LEN_OFFSET 8 #define SMF_HEADER_LENGTH 10 ! #define SMF_ENTRY_LENGTH 20 /* * Share mode record offsets. --- 46,52 ---- #define SMF_FILENAME_LEN_OFFSET 8 #define SMF_HEADER_LENGTH 10 ! #define SMF_ENTRY_LENGTH 24 /* * Share mode record offsets. *************** *** 58,63 **** --- 58,64 ---- #define SME_PID_OFFSET 12 #define SME_PORT_OFFSET 16 #define SME_OPLOCK_TYPE_OFFSET 18 + #define SME_CNUM_OFFSET 20 /* we need world read for smbstatus to function correctly */ #ifdef SECURE_SHARE_MODES *************** *** 381,386 **** --- 382,389 ---- 8 - share_mode 12 - pid 16 - oplock port (if oplocks in use) - 2 bytes. + 18 - oplock type (if oplocks in use) - 2 bytes. + 20 - cnum - 4 bytes */ share_name(conn, dev, inode, fname); *************** *** 452,457 **** --- 455,461 ---- share_array[num_entries_copied].pid = pid; share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); + share_array[num_entries_copied].cnum = IVAL(p,SME_CNUM_OFFSET); num_entries_copied++; } *************** *** 498,503 **** --- 502,508 ---- SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port); SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); + SIVAL(p,SME_CNUM_OFFSET,share_array[i].cnum); } newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied); *************** *** 811,816 **** --- 816,822 ---- SIVAL(p,SME_PID_OFFSET,(uint32)pid); SSVAL(p,SME_PORT_OFFSET,port); SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); + SIVAL(p,SME_CNUM_OFFSET,fsp->conn->cnum); num_entries++; *************** *** 1083,1088 **** --- 1089,1095 ---- e.time.tv_usec = IVAL(p,SME_USEC_OFFSET); e.op_port = SVAL(p,SME_PORT_OFFSET); e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); + e.cnum = IVAL(p,SME_CNUM_OFFSET); if (process_exists(e.pid)) { fn(&e, fname); *** source/include/smb.h.orig Thu Nov 11 13:36:01 1999 --- source/include/smb.h Fri Nov 12 18:16:03 1999 *************** *** 724,729 **** --- 724,730 ---- typedef struct { pid_t pid; + int cnum; /* for status display */ uint16 op_port; uint16 op_type; int share_mode; *************** *** 886,892 **** #define FLAG_DOS_STRING 0x40 /* convert from UNIX to DOS codepage when reading this string. */ #ifndef LOCKING_VERSION ! #define LOCKING_VERSION 4 #endif /* LOCKING_VERSION */ /* these are useful macros for checking validity of handles */ --- 887,893 ---- #define FLAG_DOS_STRING 0x40 /* convert from UNIX to DOS codepage when reading this string. */ #ifndef LOCKING_VERSION ! #define LOCKING_VERSION 5 #endif /* LOCKING_VERSION */ /* these are useful macros for checking validity of handles */ *** source/utils/status.c.orig Wed Oct 13 15:27:03 1999 --- source/utils/status.c Fri Nov 12 18:30:05 1999 *************** *** 41,47 **** struct session_record{ pid_t pid; uid_t uid; ! char machine[31]; time_t start; struct session_record *next; } *srecs; --- 41,49 ---- struct session_record{ pid_t pid; uid_t uid; ! int cnum; ! char machine[32]; ! char service[24]; time_t start; struct session_record *next; } *srecs; *************** *** 57,66 **** --- 59,104 ---- int shares_only = 0; /* Added by RJS */ int locks_only = 0; /* Added by RJS */ + #define talloc(t) ((t *) malloc(sizeof (t))) + /* we need these because we link to locking*.o */ void become_root(BOOL save_dir) {} void unbecome_root(BOOL restore_dir) {} + struct timeval now; + + /**************************************************************************** + the date and time as a string + ****************************************************************************/ + static char *fmttime(time_t *t) + { + static char TimeBuf[100]; + struct tm *tm = LocalTime(t); + + #ifdef HAVE_STRFTIME + strftime(TimeBuf, sizeof(TimeBuf), "%Y/%m/%d %H:%M:%S%n", tm); + #else + safe_strcpy(TimeBuf, asctime(tm), sizeof(TimeBuf) - 1); + #endif + + return TimeBuf; + } + + static char *prtimediff(time_t t) + { + static char TimeBuf[100]; + + if (t < (60*60)) + snprintf(TimeBuf, sizeof(TimeBuf), "%2ldm%02lds", t/60, t%60); + else if ((t = (t+30)/60) < (24*60)) + snprintf(TimeBuf, sizeof(TimeBuf), "%2ldh%02ldm", t/60, t%60); + else if ((t = (t+30)/60) < (7*24)) + snprintf(TimeBuf, sizeof(TimeBuf), "%2ldd%02ldh", t/24, t%24); + else + snprintf(TimeBuf, sizeof(TimeBuf), "%2ldw%02ldd", t/(7*24), (t/24)%7); + return TimeBuf; + } + /* added by OH */ static void Ucrit_addUsername(char *username) *************** *** 77,142 **** return 0; } - static void Ucrit_addPid(pid_t pid) - { - int i; - if ( !Ucrit_IsActive) return; - for (i=0;ipid)) { ! printf("%-5d ",(int)e->pid); ! switch ((e->share_mode>>4)&0xF) { ! case DENY_NONE: printf("DENY_NONE "); break; ! case DENY_ALL: printf("DENY_ALL "); break; ! case DENY_DOS: printf("DENY_DOS "); break; ! case DENY_READ: printf("DENY_READ "); break; ! case DENY_WRITE:printf("DENY_WRITE "); break; } ! switch (e->share_mode&0xF) { ! case 0: printf("RDONLY "); break; ! case 1: printf("WRONLY "); break; ! case 2: printf("RDWR "); break; } ! if((e->op_type & ! (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == ! (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) ! printf("EXCLUSIVE+BATCH "); ! else if (e->op_type & EXCLUSIVE_OPLOCK) ! printf("EXCLUSIVE "); ! else if (e->op_type & BATCH_OPLOCK) ! printf("BATCH "); ! else if (e->op_type & LEVEL_II_OPLOCK) ! printf("LEVEL_II "); ! else ! printf("NONE "); ! ! printf(" %s %s",dos_to_unix(fname,False), ! asctime(LocalTime((time_t *)&e->time.tv_sec))); } } --- 115,192 ---- return 0; } static void print_share_mode(share_mode_entry *e, char *fname) { static int count; ! struct session_record *ptr; ! char *user; ! char *share; ! ! user = ""; ! share = NULL; ! for (ptr=srecs; ptr!=NULL; ptr=ptr->next) { ! if (ptr->pid == e->pid && ptr->cnum == e->cnum) { ! user = uidtoname(ptr->uid); ! share = ptr->service; ! break; ! } } ! if (!Ucrit_checkUsername(user)) /* added by OH */ ! return; ! if (count==0) { ! if (locks_only) { ! printf(" Pid Deny R/W Oplock Held Name\n"); ! printf("---------------------------------------\n"); } ! else { ! printf("Locked files:\n"); ! if (Ucrit_IsActive) ! printf(" Pid Deny R/W Oplock Held Share Name\n"); ! else ! printf("User Deny R/W Oplock Held Share Name\n"); ! printf( "------------------------------------------------\n"); } + } + count++; ! if (Ucrit_IsActive||locks_only) ! printf("%6d ",e->pid); ! else if (share != NULL) ! printf("%-8.8s ",user); ! else ! printf("[%6d] ",e->pid); ! switch ((e->share_mode>>4)&0xF) { ! case DENY_NONE: printf("NONE "); break; ! case DENY_ALL: printf("ALL "); break; ! case DENY_DOS: printf("DOS "); break; ! case DENY_READ: printf("READ "); break; ! case DENY_WRITE:printf("WRIT "); break; } + switch (e->share_mode&0xF) { + case 0: printf("R/- "); break; + case 1: printf("-/W "); break; + case 2: printf("R/W "); break; + } + + if((e->op_type & + (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == + (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) + printf("EXCL+BTCH "); + else if (e->op_type & EXCLUSIVE_OPLOCK) + printf("EXCLUSIVE "); + else if (e->op_type & BATCH_OPLOCK) + printf("BATCH "); + else if (e->op_type & LEVEL_II_OPLOCK) + printf("LEVEL_II "); + else + printf("NONE "); + + printf("%s ",prtimediff(now.tv_sec - e->time.tv_sec)); + if (share!=NULL&&!locks_only) + printf("%7.23s ",share); + printf("%s\n",dos_to_unix(fname,False)); + } *************** *** 155,160 **** --- 205,211 ---- TimeInit(); + GetTimeOfDay(&now); setup_logging(argv[0],True); charset_initialise(); *************** *** 191,197 **** Ucrit_addUsername(optarg); /* added by OH */ break; default: ! fprintf(stderr, "Usage: %s [-d] [-L] [-p] [-S] [-s configfile] [-u username]\n", *argv); /* changed by OH */ return (-1); } } --- 242,248 ---- Ucrit_addUsername(optarg); /* added by OH */ break; default: ! fprintf(stderr, "Usage: %s [-b] [-d] [-L] [-p] [-S] [-s configfile] [-u username]\n", *argv); /* changed by OH */ return (-1); } } *************** *** 249,255 **** ) { if (brief) ! { ptr=srecs; while (ptr!=NULL) { --- 300,306 ---- ) { if (brief) ! { /* brief, only need to keep details of first connect */ ptr=srecs; while (ptr!=NULL) { *************** *** 261,292 **** } ptr=ptr->next; } - if (ptr==NULL) - { - ptr=(struct session_record *) malloc(sizeof(struct session_record)); - ptr->uid=crec.uid; - ptr->pid=crec.pid; - ptr->start=crec.start; - strncpy(ptr->machine,crec.machine,30); - ptr->machine[30]='\0'; - ptr->next=srecs; - srecs=ptr; - } } ! else { - Ucrit_addPid(crec.pid); /* added by OH */ if (processes_only) { if (last_pid != crec.pid) printf("%d\n",(int)crec.pid); last_pid = crec.pid; /* XXXX we can still get repeats, have to add a sort at some time */ } ! else printf("%-10.10s %-8s %-8s %5d %-8s (%s) %s", ! crec.name,uidtoname(crec.uid),gidtoname(crec.gid),(int)crec.pid, ! crec.machine,crec.addr, asctime(LocalTime(&crec.start))); } } } --- 312,348 ---- } ptr=ptr->next; } } ! if ((!brief||ptr==NULL)&&(ptr=talloc(struct session_record))!=NULL) ! { ! ptr->uid=crec.uid; ! ptr->pid=crec.pid; ! ptr->cnum=crec.cnum; ! ptr->start=crec.start; ! strncpy(ptr->machine,crec.machine,31); ! ptr->machine[31]='\0'; ! strncpy(ptr->service,crec.name,23); ! ptr->machine[23]='\0'; ! ptr->next=srecs; ! srecs=ptr; ! } ! if (!brief) { if (processes_only) { if (last_pid != crec.pid) printf("%d\n",(int)crec.pid); last_pid = crec.pid; /* XXXX we can still get repeats, have to add a sort at some time */ } ! else if (verbose) printf("%-10.10s %-8s %-8s %5d %-8s (%s) %s", ! crec.name,uidtoname(crec.uid),gidtoname(crec.gid), ! (int)crec.pid,crec.machine,crec.addr, asctime(LocalTime(&crec.start))); + else + printf("%-10.10s %-8s %-8s %5d %-8s %s", + crec.name,uidtoname(crec.uid),gidtoname(crec.gid), + (int)crec.pid,crec.machine,fmttime(&crec.start)); } } }