× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



If resource level security/access is properly implemented, such that no applications adopt all authorities, even if application or group authority is enabled, and if *ALLOBJ special authority is not an issue [directly, or from a group], then the following is sufficient to prevent any insert, update, or delete activity against the copy of the file in the archival library:
crtusrprf PURGE /* no groups, no owned/adopting applications */
signon or run job as user PURGE, to perform the following:
crtlib PURGE aut(*use) crtaut(*use) crtobjaud(*change)
create all files into library PURGE with AUT(*LIBCRTAUT)
By isolating the ownership to a separate profile and only *PUBLIC authority of *USE, only users with *ALLOBJ special authority should be able to access for insert/update/delete activity. If only certain users should be authorized to the library and files of archival data [either now, or if possibly in the future], then an option is to use a *AUTL name for AUT() and CRTAUT(), and assign *PUBLIC *EXCLUDE to the *AUTL, and assign each user added to the list to have *USE. Note: A file can be opened for OPTION(*ALL) [opened for all I/O options], but the actual non-read I/O requests will be denied when the authority is *USE.

Inhibit Write is good for testing applications that are known to be compatible with such testing. However some update programs could loop for use of InhWrt(*YES), due to programmed assumptions. Since the program will infer the operation completes even though nothing happened, an assumption about that completed I/O request could lead the programmed logic astray. For example, the following logic is problematic for a delete request that does not actually effect the delete:
dowhile not_found;
call a program to delete a record with a specific key
if key not found, set not_found
end
The above sequence of repeated calls, depending on actual coding, could result in an endless loop trying to delete the same record.

A good way to prevent insert, update, and delete activity against a database file is to defer to the database for enforcement. This ensures that irrespective of any [special, private, or adopted/application] authorities or [properly] implemented inhibit write capabilities enforced by the data management, the database is the arbiter via the registered trigger. Unfortunately excessive authority [e.g. *ALLOBJ] would enable CHGPFTRG STATE(*DISABLED) or RMVPFTRG.
That can be accomplished by creating one program to be used for a *BEFORE trigger for each event, then assigning every file that same trigger program for all three of those events. The trigger need do nothing more than issue a diagnostic message that says "This is the archival data library. No updates allowed!", and then issue an escape message so the requested I/O fails. Thus any programs that were not inquiry only would fail if they accidentally directed against those files.

With DDS created files, the ALWUPD(*NO) and ALWDLT(*NO) can be used, such that effectively only full refreshes would be allowed for any situation when only Insert activity is insufficient to establish the data sets. The given scenario suggests insert would be all that is necessary, since the archival copy of the data is only pruned records; i.e. a pruned record can not be changed, because it no longer exists, thus an inability to update is a non-issue. Using this approach, only writes would need to be prevented, from all but the prune/archival routine -- for which deferral to other [e.g. of those above] options is required.

If locking is attempted as [an additional] preventive to any access other than read, be sure to modify the archival files to have the WAITFILE(*IMMED) so if/when an application does attempt more than OPTION(*INP) [more than read-only] then there will not be a long wait to find out the application is just going to fail -- it fails immediately when trying to open the archival copy of the file for other than read.

Of course any of these approaches could work in conjunction with any of the others.

Almost all other approaches I can think of would have to see modifications to the application. The only exception, being one that I recommend against using, even though it is an inviting option. That is the Database File Open Exit Program. Input to the exit program includes both the library name and the open options, and thus the ability exists easily to determine if the program should, and then the ability to set a feedback via its /return code/ to deny the open when the file is in the archival library. I do not recommend that exit because it will be called for effectively every database full open performed on the system. It would be best if there was instead, a Database-Open-event [effective] trigger defined at either the file or member level; optionally an unchangeable attribute [so as not to be defeated], like the ALWUPD & ALWDLT.

Since SQL TABLE does not support ALWUPD & ALWDLT, it might be worthwhile to submit a design change request asking for the ability to perform something like the imaginary request:
CHGPFALW ALWUPD(*NO|*SAME) ALWDLT(*NO|*SAME) ALWWRT(*NO|*SAME).
Admittedly not really a valid CHGxxx command since the command would allow only unidirectional change, but such a command would enable SQL TABLE to get the same protection available to CRTPF, and it would add the additional ability to make a truly read-only file. The obvious concern would be for lack of ability to continue insert from future pruning, so that would have to be resolved by the sequence of actions like either of:
rnm-alwNot-> create-> copy-from-rnm-> prune/add-> ChgAlw-> dlt-rnm
or
create-like-> copy-to-like-> prune+add-to-like-> save-like->
rst-like-over-alwNot-> dlt-like
The obvious complaint to come with such an implementation would be, "But why not enable resetting to have ALWxxx(*YES)," and the response is... "Because the attributes must be permanent, to ensure they are not defeated since being set." FWiW the ALWWRT [or ALWINS] was presumably never externalized because when originated, having been manifest only for CRTPF interface, the obvious catch-22 is that there would be no ability to populate, given an inability to write. However that can be /circumvented/ by either a data-only restore [which is not a write], or if the ability to turn off the allowed capabilities was extended to some point in time after the create -- by for example, CHGPFALW.

Another design change request idea: add a new /return code/ to the database file open exit which tells the DB Open to force the open to be 'input only' irrespective of what open options were specified; presumably resulting in a message logged to suggest that the open options were overridden -- like conditions CPF4015, CPF4028, etc.

Regards, Chuck

As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:
Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.