@@ -157,24 +157,32 @@ int
157157lo_read (int fd , char * buf , int len )
158158{
159159 int status ;
160+ LargeObjectDesc * lobj ;
160161
161162 if (fd < 0 || fd >= cookies_size || cookies [fd ] == NULL )
162163 ereport (ERROR ,
163164 (errcode (ERRCODE_UNDEFINED_OBJECT ),
164165 errmsg ("invalid large-object descriptor: %d" , fd )));
166+ lobj = cookies [fd ];
165167
166- /* Permission checks */
167- if (!lo_compat_privileges &&
168- pg_largeobject_aclcheck_snapshot (cookies [fd ]-> id ,
169- GetUserId (),
170- ACL_SELECT ,
171- cookies [fd ]-> snapshot ) != ACLCHECK_OK )
172- ereport (ERROR ,
173- (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
174- errmsg ("permission denied for large object %u" ,
175- cookies [fd ]-> id )));
168+ /* We don't bother to check IFS_RDLOCK, since it's always set */
169+
170+ /* Permission checks --- first time through only */
171+ if ((lobj -> flags & IFS_RD_PERM_OK ) == 0 )
172+ {
173+ if (!lo_compat_privileges &&
174+ pg_largeobject_aclcheck_snapshot (lobj -> id ,
175+ GetUserId (),
176+ ACL_SELECT ,
177+ lobj -> snapshot ) != ACLCHECK_OK )
178+ ereport (ERROR ,
179+ (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
180+ errmsg ("permission denied for large object %u" ,
181+ lobj -> id )));
182+ lobj -> flags |= IFS_RD_PERM_OK ;
183+ }
176184
177- status = inv_read (cookies [ fd ] , buf , len );
185+ status = inv_read (lobj , buf , len );
178186
179187 return status ;
180188}
@@ -183,30 +191,36 @@ int
183191lo_write (int fd , const char * buf , int len )
184192{
185193 int status ;
194+ LargeObjectDesc * lobj ;
186195
187196 if (fd < 0 || fd >= cookies_size || cookies [fd ] == NULL )
188197 ereport (ERROR ,
189198 (errcode (ERRCODE_UNDEFINED_OBJECT ),
190199 errmsg ("invalid large-object descriptor: %d" , fd )));
200+ lobj = cookies [fd ];
191201
192- if ((cookies [ fd ] -> flags & IFS_WRLOCK ) == 0 )
202+ if ((lobj -> flags & IFS_WRLOCK ) == 0 )
193203 ereport (ERROR ,
194204 (errcode (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE ),
195205 errmsg ("large object descriptor %d was not opened for writing" ,
196206 fd )));
197207
198- /* Permission checks */
199- if (!lo_compat_privileges &&
200- pg_largeobject_aclcheck_snapshot (cookies [fd ]-> id ,
201- GetUserId (),
202- ACL_UPDATE ,
203- cookies [fd ]-> snapshot ) != ACLCHECK_OK )
204- ereport (ERROR ,
205- (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
206- errmsg ("permission denied for large object %u" ,
207- cookies [fd ]-> id )));
208+ /* Permission checks --- first time through only */
209+ if ((lobj -> flags & IFS_WR_PERM_OK ) == 0 )
210+ {
211+ if (!lo_compat_privileges &&
212+ pg_largeobject_aclcheck_snapshot (lobj -> id ,
213+ GetUserId (),
214+ ACL_UPDATE ,
215+ lobj -> snapshot ) != ACLCHECK_OK )
216+ ereport (ERROR ,
217+ (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
218+ errmsg ("permission denied for large object %u" ,
219+ lobj -> id )));
220+ lobj -> flags |= IFS_WR_PERM_OK ;
221+ }
208222
209- status = inv_write (cookies [ fd ] , buf , len );
223+ status = inv_write (lobj , buf , len );
210224
211225 return status ;
212226}
@@ -230,8 +244,8 @@ lo_lseek(PG_FUNCTION_ARGS)
230244 if (status != (int32 ) status )
231245 ereport (ERROR ,
232246 (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
233- errmsg ("lo_lseek result out of range for large-object descriptor %d" ,
234- fd )));
247+ errmsg ("lo_lseek result out of range for large-object descriptor %d" ,
248+ fd )));
235249
236250 PG_RETURN_INT32 ((int32 ) status );
237251}
@@ -303,8 +317,8 @@ lo_tell(PG_FUNCTION_ARGS)
303317 if (offset != (int32 ) offset )
304318 ereport (ERROR ,
305319 (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
306- errmsg ("lo_tell result out of range for large-object descriptor %d" ,
307- fd )));
320+ errmsg ("lo_tell result out of range for large-object descriptor %d" ,
321+ fd )));
308322
309323 PG_RETURN_INT32 ((int32 ) offset );
310324}
@@ -558,30 +572,48 @@ lo_export(PG_FUNCTION_ARGS)
558572 * lo_truncate -
559573 * truncate a large object to a specified length
560574 */
561- Datum
562- lo_truncate ( PG_FUNCTION_ARGS )
575+ static void
576+ lo_truncate_internal ( int32 fd , int64 len )
563577{
564- int32 fd = PG_GETARG_INT32 (0 );
565- int32 len = PG_GETARG_INT32 (1 );
578+ LargeObjectDesc * lobj ;
566579
567580 if (fd < 0 || fd >= cookies_size || cookies [fd ] == NULL )
568581 ereport (ERROR ,
569582 (errcode (ERRCODE_UNDEFINED_OBJECT ),
570583 errmsg ("invalid large-object descriptor: %d" , fd )));
584+ lobj = cookies [fd ];
571585
572- /* Permission checks */
573- if (!lo_compat_privileges &&
574- pg_largeobject_aclcheck_snapshot (cookies [fd ]-> id ,
575- GetUserId (),
576- ACL_UPDATE ,
577- cookies [fd ]-> snapshot ) != ACLCHECK_OK )
586+ if ((lobj -> flags & IFS_WRLOCK ) == 0 )
578587 ereport (ERROR ,
579- (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
580- errmsg ("permission denied for large object %u" ,
581- cookies [fd ]-> id )));
588+ (errcode (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE ),
589+ errmsg ("large object descriptor %d was not opened for writing" ,
590+ fd )));
591+
592+ /* Permission checks --- first time through only */
593+ if ((lobj -> flags & IFS_WR_PERM_OK ) == 0 )
594+ {
595+ if (!lo_compat_privileges &&
596+ pg_largeobject_aclcheck_snapshot (lobj -> id ,
597+ GetUserId (),
598+ ACL_UPDATE ,
599+ lobj -> snapshot ) != ACLCHECK_OK )
600+ ereport (ERROR ,
601+ (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
602+ errmsg ("permission denied for large object %u" ,
603+ lobj -> id )));
604+ lobj -> flags |= IFS_WR_PERM_OK ;
605+ }
582606
583- inv_truncate (cookies [fd ], len );
607+ inv_truncate (lobj , len );
608+ }
584609
610+ Datum
611+ lo_truncate (PG_FUNCTION_ARGS )
612+ {
613+ int32 fd = PG_GETARG_INT32 (0 );
614+ int32 len = PG_GETARG_INT32 (1 );
615+
616+ lo_truncate_internal (fd , len );
585617 PG_RETURN_INT32 (0 );
586618}
587619
@@ -591,24 +623,7 @@ lo_truncate64(PG_FUNCTION_ARGS)
591623 int32 fd = PG_GETARG_INT32 (0 );
592624 int64 len = PG_GETARG_INT64 (1 );
593625
594- if (fd < 0 || fd >= cookies_size || cookies [fd ] == NULL )
595- ereport (ERROR ,
596- (errcode (ERRCODE_UNDEFINED_OBJECT ),
597- errmsg ("invalid large-object descriptor: %d" , fd )));
598-
599- /* Permission checks */
600- if (!lo_compat_privileges &&
601- pg_largeobject_aclcheck_snapshot (cookies [fd ]-> id ,
602- GetUserId (),
603- ACL_UPDATE ,
604- cookies [fd ]-> snapshot ) != ACLCHECK_OK )
605- ereport (ERROR ,
606- (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
607- errmsg ("permission denied for large object %u" ,
608- cookies [fd ]-> id )));
609-
610- inv_truncate (cookies [fd ], len );
611-
626+ lo_truncate_internal (fd , len );
612627 PG_RETURN_INT32 (0 );
613628}
614629
0 commit comments