@@ -157,24 +157,32 @@ int
157
157
lo_read (int fd , char * buf , int len )
158
158
{
159
159
int status ;
160
+ LargeObjectDesc * lobj ;
160
161
161
162
if (fd < 0 || fd >= cookies_size || cookies [fd ] == NULL )
162
163
ereport (ERROR ,
163
164
(errcode (ERRCODE_UNDEFINED_OBJECT ),
164
165
errmsg ("invalid large-object descriptor: %d" , fd )));
166
+ lobj = cookies [fd ];
165
167
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
+ }
176
184
177
- status = inv_read (cookies [ fd ] , buf , len );
185
+ status = inv_read (lobj , buf , len );
178
186
179
187
return status ;
180
188
}
@@ -183,30 +191,36 @@ int
183
191
lo_write (int fd , const char * buf , int len )
184
192
{
185
193
int status ;
194
+ LargeObjectDesc * lobj ;
186
195
187
196
if (fd < 0 || fd >= cookies_size || cookies [fd ] == NULL )
188
197
ereport (ERROR ,
189
198
(errcode (ERRCODE_UNDEFINED_OBJECT ),
190
199
errmsg ("invalid large-object descriptor: %d" , fd )));
200
+ lobj = cookies [fd ];
191
201
192
- if ((cookies [ fd ] -> flags & IFS_WRLOCK ) == 0 )
202
+ if ((lobj -> flags & IFS_WRLOCK ) == 0 )
193
203
ereport (ERROR ,
194
204
(errcode (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE ),
195
205
errmsg ("large object descriptor %d was not opened for writing" ,
196
206
fd )));
197
207
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
+ }
208
222
209
- status = inv_write (cookies [ fd ] , buf , len );
223
+ status = inv_write (lobj , buf , len );
210
224
211
225
return status ;
212
226
}
@@ -230,8 +244,8 @@ lo_lseek(PG_FUNCTION_ARGS)
230
244
if (status != (int32 ) status )
231
245
ereport (ERROR ,
232
246
(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 )));
235
249
236
250
PG_RETURN_INT32 ((int32 ) status );
237
251
}
@@ -303,8 +317,8 @@ lo_tell(PG_FUNCTION_ARGS)
303
317
if (offset != (int32 ) offset )
304
318
ereport (ERROR ,
305
319
(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 )));
308
322
309
323
PG_RETURN_INT32 ((int32 ) offset );
310
324
}
@@ -558,30 +572,48 @@ lo_export(PG_FUNCTION_ARGS)
558
572
* lo_truncate -
559
573
* truncate a large object to a specified length
560
574
*/
561
- Datum
562
- lo_truncate ( PG_FUNCTION_ARGS )
575
+ static void
576
+ lo_truncate_internal ( int32 fd , int64 len )
563
577
{
564
- int32 fd = PG_GETARG_INT32 (0 );
565
- int32 len = PG_GETARG_INT32 (1 );
578
+ LargeObjectDesc * lobj ;
566
579
567
580
if (fd < 0 || fd >= cookies_size || cookies [fd ] == NULL )
568
581
ereport (ERROR ,
569
582
(errcode (ERRCODE_UNDEFINED_OBJECT ),
570
583
errmsg ("invalid large-object descriptor: %d" , fd )));
584
+ lobj = cookies [fd ];
571
585
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 )
578
587
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
+ }
582
606
583
- inv_truncate (cookies [fd ], len );
607
+ inv_truncate (lobj , len );
608
+ }
584
609
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 );
585
617
PG_RETURN_INT32 (0 );
586
618
}
587
619
@@ -591,24 +623,7 @@ lo_truncate64(PG_FUNCTION_ARGS)
591
623
int32 fd = PG_GETARG_INT32 (0 );
592
624
int64 len = PG_GETARG_INT64 (1 );
593
625
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 );
612
627
PG_RETURN_INT32 (0 );
613
628
}
614
629
0 commit comments