mirror of
https://github.com/obarthel/amiga-smbfs.git
synced 2025-12-08 14:58:35 +00:00
The ACTION_SETDATE operation again changes both the file/directory creation date/time and the last modification date/time. Because some SMB servers will not return a valid modification date/time, the creation date/time will be substituted when directory entry information is converted into the appropriate AmigaDOS data structures. This is problematic if only the modification time/dated is updated by the ACTION_SETDATE operation because the change may appear not to "stick". The SMB function which would be used to update both the modification and the creation time stamps did not take care to preserve the creation time stamp. This might have contributed to the ACTION_SETDATE operation not having a noticeable effect. The debug code no longer uses FORMAT_DEF for converting AmigaDOS time stamp information into readable text, but uses FORMAT_DOS instead. This is an attempt to track down a hard to detect bug in the debug code which might be related to locale.library date conversion. Because the buffer size for the date and time information is limited, the locale settings might just produce too much text to fit into the buffers. But that's only a theory so far... The functions which the debug code uses to prepare 64 bit integers and strings for display are now a bit more paranoid in watching the lengths of the resulting strings, reporting possible buffer overflows. Went over all the debug output text format strings with a fine-toothed comb and actually found a few instances of the formatting parameters not being entirely correct. The assert.c code makes a bit more of an effort to handle NULL strings for display. The non-debug builds of smbfs now complain again if any of the debug parameters are being used.
386 lines
7.3 KiB
C
386 lines
7.3 KiB
C
/* an example of how to use ExAll */
|
|
|
|
/*
|
|
* Updated with a set of test features which exercise the
|
|
* various options of ExAll():
|
|
*
|
|
* - Set the size of the buffer, e.g. BUFFER=500 (default
|
|
* is BUFFER=4096).
|
|
*
|
|
* - Select which type of information should be retrieved,
|
|
* e.g. TYPE=NAME (default is TYPE=OWNER). Possible choices
|
|
* are NAME, TYPE, SIZE, PROTECTION, DATE, COMMENT and
|
|
* OWNER.
|
|
*
|
|
* - Limit the number of directory entries to retrieve, e.g.
|
|
* MAXENTRIES=10 (no limit is set by default). This feature
|
|
* requires Kickstart 3.0 or better to work.
|
|
*
|
|
* Hit [Ctrl]+C to stop reading directory entries or use the
|
|
* shell "Break" command.
|
|
*/
|
|
|
|
#include <exec/types.h>
|
|
#include <exec/ports.h>
|
|
#include <exec/memory.h>
|
|
|
|
#include <dos/dos.h>
|
|
#include <dos/dosextens.h>
|
|
#include <dos/dosasl.h>
|
|
#include <dos/exall.h>
|
|
|
|
#if defined (__GNUC__)
|
|
#if defined (__amigaos4__)
|
|
#include <dos/obsolete.h>
|
|
#endif /* __amigaos4__ */
|
|
|
|
#include <proto/exec.h>
|
|
#include <proto/dos.h>
|
|
#else
|
|
extern struct Library *SysBase;
|
|
extern struct Library *DOSBase;
|
|
|
|
#include <pragmas/exec_pragmas.h>
|
|
#include <pragmas/dos_pragmas.h>
|
|
|
|
#include <clib/exec_protos.h>
|
|
#include <clib/dos_protos.h>
|
|
#endif /* __GNUC__ */
|
|
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#define BUFFSIZE 4096
|
|
|
|
int
|
|
main(int argc,char *argv[])
|
|
{
|
|
struct
|
|
{
|
|
STRPTR Name;
|
|
STRPTR Pattern;
|
|
LONG * BufferSize;
|
|
STRPTR Type;
|
|
LONG * MaxEntries;
|
|
} args;
|
|
|
|
struct RDArgs * rda;
|
|
BPTR obj_lock;
|
|
LONG res2, more;
|
|
struct ExAllData *buffer = NULL;
|
|
struct ExAllData *ead;
|
|
struct ExAllControl *control = NULL;
|
|
LONG rc = RETURN_ERROR;
|
|
char pattern[256];
|
|
ULONG total_num_entries = 0;
|
|
int max_entries = 0;
|
|
int buffer_size = 0;
|
|
int type;
|
|
int i;
|
|
|
|
memset(&args,0,sizeof(args));
|
|
|
|
rda = ReadArgs("NAME/A,PATTERN/K,BUF=BUFFER/K/N,TYPE/K,MAXENTRIES/K/N", (LONG *)&args, NULL);
|
|
if (rda == NULL)
|
|
{
|
|
PrintFault(IoErr(),FilePart(argv[0]));
|
|
goto cleanup;
|
|
}
|
|
|
|
if (args.BufferSize != NULL)
|
|
buffer_size = (*args.BufferSize);
|
|
else
|
|
buffer_size = BUFFSIZE;
|
|
|
|
if (args.Type != NULL)
|
|
{
|
|
char key[16]; /* Enough for "protection". */
|
|
int c;
|
|
|
|
for (i = 0 ; i < (int)sizeof(key)-1 ; i++)
|
|
{
|
|
c = args.Type[i];
|
|
if(c == '\0')
|
|
break;
|
|
|
|
key[i] = tolower(c);
|
|
}
|
|
|
|
key[i] = '\0';
|
|
|
|
if (strcmp(key,"name") == 0)
|
|
{
|
|
type = ED_NAME;
|
|
}
|
|
else if (strcmp(key,"type") == 0)
|
|
{
|
|
type = ED_TYPE;
|
|
}
|
|
else if (strcmp(key,"size") == 0)
|
|
{
|
|
type = ED_SIZE;
|
|
}
|
|
else if (strcmp(key,"protection") == 0)
|
|
{
|
|
type = ED_PROTECTION;
|
|
}
|
|
else if (strcmp(key,"date") == 0)
|
|
{
|
|
type = ED_DATE;
|
|
}
|
|
else if (strcmp(key,"comment") == 0)
|
|
{
|
|
type = ED_COMMENT;
|
|
}
|
|
else if (strcmp(key,"owner") == 0)
|
|
{
|
|
type = ED_OWNER;
|
|
}
|
|
else
|
|
{
|
|
Printf("Type \"%s\" not known.\n", args.Type);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
type = ED_OWNER;
|
|
}
|
|
|
|
if (args.MaxEntries != NULL)
|
|
{
|
|
if(DOSBase->lib_Version < 39)
|
|
{
|
|
Printf("Ignoring MAXENTRIES=%ld (dos.library V39 or better required)\n",(*args.MaxEntries));
|
|
}
|
|
else
|
|
{
|
|
if((*args.MaxEntries) < 1)
|
|
{
|
|
PutStr("MAXENTRIES must be > 0\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
max_entries = (*args.MaxEntries);
|
|
}
|
|
}
|
|
|
|
/* control MUST be allocated by AllocDosObject! */
|
|
control = (struct ExAllControl *) AllocDosObject(DOS_EXALLCONTROL, NULL);
|
|
buffer = (struct ExAllData *) AllocMem(buffer_size, MEMF_PUBLIC|MEMF_CLEAR);
|
|
|
|
/* always check allocations! */
|
|
if (control == NULL || buffer == NULL)
|
|
goto cleanup;
|
|
|
|
if (args.Pattern != NULL)
|
|
{
|
|
/* parse the pattern for eac_MatchString */
|
|
if (ParsePatternNoCase(args.Pattern, pattern, sizeof(pattern)) == -1)
|
|
{
|
|
PrintFault(IoErr(), args.Pattern);
|
|
goto cleanup;
|
|
}
|
|
|
|
control->eac_MatchString = pattern;
|
|
}
|
|
|
|
/* lock the directory */
|
|
obj_lock = Lock(args.Name, SHARED_LOCK);
|
|
if (obj_lock == (BPTR)NULL)
|
|
{
|
|
PrintFault(IoErr(), args.Name);
|
|
goto cleanup;
|
|
}
|
|
|
|
control->eac_LastKey = 0; /* paranoia */
|
|
|
|
Printf("Buffer size = %ld bytes\n", buffer_size);
|
|
|
|
do /* while more */
|
|
{
|
|
if(CheckSignal(SIGBREAKF_CTRL_C))
|
|
{
|
|
PrintFault(ERROR_BREAK, argv[0]);
|
|
|
|
rc = RETURN_WARN;
|
|
break;
|
|
}
|
|
|
|
more = ExAll(obj_lock, buffer, buffer_size, type, control);
|
|
res2 = IoErr();
|
|
|
|
/* Workaround for V37 ROM/disk filesystem bug. */
|
|
if(!more && res2 == ERROR_BAD_NUMBER && type == ED_OWNER)
|
|
{
|
|
type = ED_COMMENT;
|
|
|
|
more = ExAll(obj_lock, buffer, buffer_size, type, control);
|
|
res2 = IoErr();
|
|
}
|
|
|
|
if (!more && res2 != ERROR_NO_MORE_ENTRIES)
|
|
{
|
|
Printf("Abnormal exit, error = %ld\n",res2);
|
|
break;
|
|
}
|
|
|
|
if (control->eac_Entries == 0)
|
|
{
|
|
/* ExAll failed normally with no entries. 'more' is usually FALSE. */
|
|
Printf("\nReturned 0 entries (more=%s); retrying...\n", more ? "TRUE" : "FALSE");
|
|
continue;
|
|
}
|
|
|
|
Printf("\nReturned %ld entries:\n",control->eac_Entries);
|
|
|
|
for(ead = buffer ; ead != NULL ; ead = ead->ed_Next)
|
|
{
|
|
if(CheckSignal(SIGBREAKF_CTRL_C))
|
|
{
|
|
PrintFault(ERROR_BREAK, argv[0]);
|
|
|
|
more = FALSE;
|
|
|
|
rc = RETURN_WARN;
|
|
break;
|
|
}
|
|
|
|
Printf("%s", ead->ed_Name);
|
|
|
|
if (type >= ED_TYPE)
|
|
{
|
|
if (ead->ed_Type > 0)
|
|
PutStr(" (dir)");
|
|
else
|
|
PutStr(" (file)");
|
|
}
|
|
|
|
if (type >= ED_SIZE)
|
|
{
|
|
if (ead->ed_Type < 0)
|
|
Printf(", size=%ld", ead->ed_Size);
|
|
}
|
|
|
|
if (type >= ED_PROTECTION)
|
|
{
|
|
char user_other_bits[11];
|
|
char owner_bits[9];
|
|
|
|
strcpy(user_other_bits, "rwed rwed");
|
|
|
|
for(i = 8 ; i < 16 ; i++)
|
|
{
|
|
if((ead->ed_Prot & (1 << i)) == 0)
|
|
{
|
|
int offset;
|
|
|
|
if(i < 12)
|
|
offset = 12 - i;
|
|
else
|
|
offset = 21 - i;
|
|
|
|
user_other_bits[offset - 1] = '-';
|
|
}
|
|
}
|
|
|
|
strcpy(owner_bits, "hsparwed");
|
|
|
|
for(i = 0 ; i < 4 ; i++)
|
|
{
|
|
if((ead->ed_Prot & (1 << i)) != 0)
|
|
owner_bits[7 - i] = '-';
|
|
}
|
|
|
|
for(i = 4 ; i < 8 ; i++)
|
|
{
|
|
if((ead->ed_Prot & (1 << i)) == 0)
|
|
owner_bits[7 - i] = '-';
|
|
}
|
|
|
|
Printf(", protection=%s %s (0x%08lx)",
|
|
user_other_bits, owner_bits, ead->ed_Prot);
|
|
}
|
|
|
|
if (type >= ED_DATE)
|
|
{
|
|
struct DateTime dat;
|
|
char date[LEN_DATSTRING],time[LEN_DATSTRING];
|
|
|
|
memset(&dat,0,sizeof(dat));
|
|
|
|
memset(date,0,sizeof(date));
|
|
memset(time,0,sizeof(time));
|
|
|
|
dat.dat_Stamp.ds_Days = ead->ed_Days;
|
|
dat.dat_Stamp.ds_Minute = ead->ed_Mins;
|
|
dat.dat_Stamp.ds_Tick = ead->ed_Ticks;
|
|
dat.dat_Format = FORMAT_DOS;
|
|
dat.dat_StrDate = date;
|
|
dat.dat_StrTime = time;
|
|
|
|
DateToStr(&dat);
|
|
|
|
Printf(", date=%s %s (%ld/%ld/%ld)",
|
|
date, time,
|
|
ead->ed_Days, ead->ed_Mins, ead->ed_Ticks);
|
|
}
|
|
|
|
if (type >= ED_COMMENT)
|
|
{
|
|
if(ead->ed_Comment != NULL)
|
|
Printf(", comment=\"%s\"", ead->ed_Comment);
|
|
else
|
|
PutStr(", comment=NULL");
|
|
}
|
|
|
|
if (type == ED_OWNER)
|
|
{
|
|
Printf(", uid=%ld, gid=%ld",
|
|
ead->ed_OwnerUID,
|
|
ead->ed_OwnerGID);
|
|
}
|
|
|
|
PutStr("\n");
|
|
|
|
total_num_entries++;
|
|
|
|
/* Check if we reached the limit of how many directory
|
|
* entries we may display.
|
|
*/
|
|
if(max_entries > 0)
|
|
{
|
|
max_entries--;
|
|
if(max_entries == 0)
|
|
{
|
|
/* Stop reading directory entries (dos.library V39
|
|
* or better required.
|
|
*/
|
|
ExAllEnd(obj_lock, buffer, buffer_size, type, control);
|
|
|
|
more = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
while (more);
|
|
|
|
UnLock(obj_lock);
|
|
|
|
Printf("Total number of entries = %lu\n", total_num_entries);
|
|
|
|
cleanup:
|
|
|
|
if (rda != NULL)
|
|
FreeArgs(rda);
|
|
|
|
if (buffer != NULL)
|
|
FreeMem(buffer, buffer_size);
|
|
|
|
if (control != NULL)
|
|
FreeDosObject(DOS_EXALLCONTROL, control);
|
|
|
|
return(rc);
|
|
}
|