00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifdef HAVE_CONFIG_H
00014 # include <config.h>
00015 #endif
00016
00017
00018 #include "io_file_p.h"
00019 #include <gwenhywfar/iolayer_be.h>
00020 #include <gwenhywfar/iorequest_be.h>
00021
00022 #include "i18n_l.h"
00023 #include <gwenhywfar/misc.h>
00024 #include <gwenhywfar/debug.h>
00025 #include <gwenhywfar/gui.h>
00026
00027 #include <assert.h>
00028 #include <errno.h>
00029 #include <string.h>
00030 #include <unistd.h>
00031 #include <fcntl.h>
00032
00033
00034
00035
00036 GWEN_INHERIT(GWEN_IO_LAYER, GWEN_IO_LAYER_FILE)
00037
00038
00039
00040 GWEN_IO_LAYER *GWEN_Io_LayerFile_new(int fdRead, int fdWrite) {
00041 GWEN_IO_LAYER *io;
00042 GWEN_IO_LAYER_FILE *xio;
00043
00044 io=GWEN_Io_Layer_new(GWEN_IO_LAYER_FILE_TYPE, NULL);
00045 assert(io);
00046 GWEN_NEW_OBJECT(GWEN_IO_LAYER_FILE, xio);
00047 assert(xio);
00048 GWEN_INHERIT_SETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_FILE, io, xio, GWEN_Io_LayerFile_freeData);
00049
00050 GWEN_Io_Layer_SetWorkOnRequestsFn(io, GWEN_Io_LayerFile_WorkOnRequests);
00051 GWEN_Io_Layer_SetAddRequestFn(io, GWEN_Io_LayerFile_AddRequest);
00052 GWEN_Io_Layer_SetDelRequestFn(io, GWEN_Io_LayerFile_DelRequest);
00053 GWEN_Io_Layer_SetHasWaitingRequestsFn(io, GWEN_Io_LayerFile_HasWaitingRequests);
00054
00055 xio->fdRead=fdRead;
00056 xio->fdWrite=fdWrite;
00057
00058 #ifndef OS_WIN32
00059
00060 if (fdRead!=-1) {
00061 int rv;
00062 long fl;
00063
00064
00065 xio->readFlags=fcntl(fdRead, F_GETFL);
00066
00067
00068 fl=xio->readFlags | O_NONBLOCK;
00069 rv=fcntl(fdRead, F_SETFL, fl);
00070 if (rv) {
00071 DBG_ERROR(GWEN_LOGDOMAIN, "fcntl(%d, F_SETFL): %s", fdRead, strerror(errno));
00072 xio->fdRead=-1;
00073 }
00074 }
00075
00076 if (fdWrite!=-1) {
00077 int rv;
00078 long fl;
00079
00080
00081 xio->writeFlags=fcntl(fdWrite, F_GETFL);
00082
00083
00084 fl=xio->writeFlags | O_NONBLOCK;
00085 rv=fcntl(fdWrite, F_SETFL, fl);
00086 if (rv) {
00087 DBG_ERROR(GWEN_LOGDOMAIN, "fcntl(%d, F_SETFL): %s", fdWrite, strerror(errno));
00088 xio->fdWrite=-1;
00089 }
00090 }
00091 #endif
00092
00093 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
00094
00095
00096 return io;
00097 }
00098
00099
00100
00101 GWENHYWFAR_CB
00102 void GWEN_Io_LayerFile_freeData(void *bp, void *p) {
00103 GWEN_IO_LAYER *io;
00104 GWEN_IO_LAYER_FILE *xio;
00105
00106 io=(GWEN_IO_LAYER*) bp;
00107 assert(io);
00108 xio=(GWEN_IO_LAYER_FILE*) p;
00109 assert(xio);
00110 if (xio->readRequest) {
00111 GWEN_IO_REQUEST *r;
00112
00113 r=xio->readRequest;
00114 xio->readRequest=NULL;
00115 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
00116 GWEN_Io_Request_free(r);
00117 }
00118 if (xio->writeRequest) {
00119 GWEN_IO_REQUEST *r;
00120
00121 r=xio->writeRequest;
00122 xio->writeRequest=NULL;
00123 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
00124 GWEN_Io_Request_free(r);
00125 }
00126 if (xio->fdRead!=-1) {
00127 if (!(GWEN_Io_Layer_GetFlags(io) & GWEN_IO_LAYER_FLAGS_DONTCLOSE))
00128 close(xio->fdRead);
00129 }
00130 if (xio->fdWrite!=-1) {
00131 if (!(GWEN_Io_Layer_GetFlags(io) & GWEN_IO_LAYER_FLAGS_DONTCLOSE))
00132 close(xio->fdWrite);
00133 }
00134 GWEN_FREE_OBJECT(xio);
00135 }
00136
00137
00138
00139 int GWEN_Io_LayerFile_GetReadFileDescriptor(const GWEN_IO_LAYER *io) {
00140 GWEN_IO_LAYER_FILE *xio;
00141
00142 assert(io);
00143 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_FILE, io);
00144 assert(xio);
00145
00146 return xio->fdRead;
00147 }
00148
00149
00150
00151 int GWEN_Io_LayerFile_GetWriteFileDescriptor(const GWEN_IO_LAYER *io) {
00152 GWEN_IO_LAYER_FILE *xio;
00153
00154 assert(io);
00155 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_FILE, io);
00156 assert(xio);
00157
00158 return xio->fdWrite;
00159 }
00160
00161
00162
00163 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerFile_WorkOnRequests(GWEN_IO_LAYER *io) {
00164 GWEN_IO_LAYER_FILE *xio;
00165 int doneSomething=0;
00166
00167 assert(io);
00168 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_FILE, io);
00169 assert(xio);
00170
00171
00172 if (xio->readRequest) {
00173 ssize_t rv;
00174 ssize_t bytesLeft;
00175 GWEN_IO_REQUEST *r;
00176
00177 r=xio->readRequest;
00178 bytesLeft=GWEN_Io_Request_GetBufferSize(r)-GWEN_Io_Request_GetBufferPos(r);
00179 rv=read(xio->fdRead,
00180 GWEN_Io_Request_GetBufferPtr(r),
00181 bytesLeft);
00182 if (rv==(ssize_t)-1) {
00183 if (errno!=EAGAIN && errno!=EINTR) {
00184 DBG_INFO(GWEN_LOGDOMAIN, "read(%d): %s", xio->fdRead, strerror(errno));
00185 xio->readRequest=NULL;
00186 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_IO);
00187 GWEN_Io_Request_free(r);
00188 doneSomething=1;
00189 }
00190
00191 }
00192 else if (rv==0) {
00193
00194 DBG_INFO(GWEN_LOGDOMAIN, "EOF met");
00195 xio->readRequest=NULL;
00196 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_EOF);
00197 GWEN_Io_Request_free(r);
00198 doneSomething=1;
00199 }
00200 else {
00201 uint32_t newPos;
00202
00203
00204 newPos=GWEN_Io_Request_GetBufferPos(r)+rv;
00205 GWEN_Io_Request_SetBufferPos(r, newPos);
00206
00207 if (rv<bytesLeft) {
00208
00209 if (!(GWEN_Io_Request_GetFlags(r) & GWEN_IO_REQUEST_FLAGS_READALL)) {
00210
00211 xio->readRequest=NULL;
00212 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00213 GWEN_Io_Request_free(r);
00214 }
00215
00216 }
00217 else {
00218
00219 xio->readRequest=NULL;
00220 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00221 GWEN_Io_Request_free(r);
00222 }
00223 doneSomething=1;
00224 }
00225 }
00226
00227
00228 if (xio->writeRequest) {
00229 ssize_t rv;
00230 ssize_t bytesLeft;
00231 GWEN_IO_REQUEST *r;
00232
00233 r=xio->writeRequest;
00234 bytesLeft=GWEN_Io_Request_GetBufferSize(r)-GWEN_Io_Request_GetBufferPos(r);
00235 rv=write(xio->fdWrite,
00236 GWEN_Io_Request_GetBufferPtr(r),
00237 bytesLeft);
00238 if (rv==(ssize_t)-1) {
00239 if (errno!=EAGAIN && errno!=EINTR) {
00240 DBG_INFO(GWEN_LOGDOMAIN, "write(%d): %s", xio->fdWrite, strerror(errno));
00241 xio->writeRequest=NULL;
00242 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_IO);
00243 GWEN_Io_Request_free(r);
00244 doneSomething=1;
00245 }
00246
00247 }
00248 else {
00249 uint32_t newPos;
00250
00251
00252 newPos=GWEN_Io_Request_GetBufferPos(r)+rv;
00253 GWEN_Io_Request_SetBufferPos(r, newPos);
00254
00255 if (newPos>=GWEN_Io_Request_GetBufferSize(r) ||
00256 !(GWEN_Io_Request_GetFlags(r) & GWEN_IO_REQUEST_FLAGS_WRITEALL)) {
00257
00258 xio->writeRequest=NULL;
00259 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00260 GWEN_Io_Request_free(r);
00261 }
00262 doneSomething=1;
00263 }
00264 }
00265
00266 return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
00267 }
00268
00269
00270
00271 int GWEN_Io_LayerFile_AddRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
00272 GWEN_IO_LAYER_FILE *xio;
00273 GWEN_IO_LAYER_STATUS st;
00274
00275 assert(io);
00276 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_FILE, io);
00277 assert(xio);
00278
00279 st=GWEN_Io_Layer_GetStatus(io);
00280
00281 switch(GWEN_Io_Request_GetType(r)) {
00282 case GWEN_Io_Request_TypeRead:
00283
00284 if (st!=GWEN_Io_Layer_StatusConnected) {
00285 DBG_INFO(GWEN_LOGDOMAIN, "File is not open");
00286 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00287 return GWEN_ERROR_NOT_OPEN;
00288 }
00289
00290
00291 if (xio->readRequest) {
00292 DBG_INFO(GWEN_LOGDOMAIN, "There already is a read request");
00293 return GWEN_ERROR_TRY_AGAIN;
00294 }
00295
00296
00297 if (xio->fdRead==-1) {
00298 DBG_INFO(GWEN_LOGDOMAIN, "File is not open for reading");
00299 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00300 return GWEN_ERROR_NOT_OPEN;
00301 }
00302
00303
00304 xio->readRequest=r;
00305 GWEN_Io_Request_Attach(xio->readRequest);
00306 break;
00307
00308 case GWEN_Io_Request_TypeWrite:
00309
00310 if (st!=GWEN_Io_Layer_StatusConnected) {
00311 DBG_INFO(GWEN_LOGDOMAIN, "File is not open");
00312 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00313 return GWEN_ERROR_NOT_OPEN;
00314 }
00315
00316
00317 if (xio->writeRequest) {
00318 DBG_INFO(GWEN_LOGDOMAIN, "There already is a write request");
00319 return GWEN_ERROR_TRY_AGAIN;
00320 }
00321
00322
00323 if (xio->fdWrite==-1) {
00324 DBG_INFO(GWEN_LOGDOMAIN, "File is not open for writing");
00325 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00326 return GWEN_ERROR_NOT_OPEN;
00327 }
00328
00329
00330 xio->writeRequest=r;
00331 GWEN_Io_Request_Attach(xio->writeRequest);
00332 break;
00333
00334 case GWEN_Io_Request_TypeDisconnect:
00335
00336 if (st!=GWEN_Io_Layer_StatusConnected) {
00337 DBG_INFO(GWEN_LOGDOMAIN, "File is not open");
00338 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00339 return GWEN_ERROR_NOT_OPEN;
00340 }
00341 else {
00342 int rv=0, rv1=0, rv2=0, rv3=0, rv4=0;
00343
00344
00345 #ifndef OS_WIN32
00346 if (xio->fdRead!=-1)
00347 rv1=fcntl(xio->fdRead, F_SETFL, xio->readFlags);
00348 if (xio->fdWrite!=-1)
00349 rv2=fcntl(xio->fdWrite, F_SETFL, xio->writeFlags);
00350 #endif
00351
00352
00353 if (!(GWEN_Io_Layer_GetFlags(io) & GWEN_IO_LAYER_FLAGS_DONTCLOSE)) {
00354 if (xio->fdRead!=-1)
00355 rv3=close(xio->fdRead);
00356 if (xio->fdWrite!=-1 && xio->fdRead!=xio->fdWrite)
00357 rv4=close(xio->fdWrite);
00358
00359
00360 xio->fdRead=-1;
00361 xio->fdWrite=-1;
00362 }
00363
00364
00365 if (rv1) rv=rv1;
00366 if (rv2) rv=rv2;
00367 if (rv3) rv=rv3;
00368 if (rv4) rv=rv4;
00369 if (rv) {
00370 DBG_INFO(GWEN_LOGDOMAIN, "Error closing file: %s", strerror(errno));
00371 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
00372 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00373 return rv;
00374 }
00375
00376
00377 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
00378 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00379 }
00380 break;
00381
00382 default:
00383 DBG_INFO(GWEN_LOGDOMAIN, "This request type is not supported (%d)", GWEN_Io_Request_GetType(r));
00384 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_SUPPORTED);
00385 return GWEN_ERROR_NOT_SUPPORTED;
00386 }
00387
00388 return 0;
00389 }
00390
00391
00392
00393 int GWEN_Io_LayerFile_DelRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
00394 GWEN_IO_LAYER_FILE *xio;
00395
00396 assert(io);
00397 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_FILE, io);
00398 assert(xio);
00399
00400 switch(GWEN_Io_Request_GetType(r)) {
00401 case GWEN_Io_Request_TypeRead:
00402 if (xio->readRequest==r) {
00403 DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted read request");
00404 GWEN_Io_Request_Finished(xio->readRequest, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
00405 GWEN_Io_Request_free(xio->readRequest);
00406 xio->readRequest=NULL;
00407 }
00408 else {
00409
00410 DBG_INFO(GWEN_LOGDOMAIN, "Read request not registered with this io layer");
00411 return GWEN_ERROR_INVALID;
00412 }
00413 break;
00414
00415 case GWEN_Io_Request_TypeWrite:
00416 if (xio->writeRequest==r) {
00417 DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted write request");
00418 GWEN_Io_Request_Finished(xio->writeRequest, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
00419 GWEN_Io_Request_free(xio->writeRequest);
00420 xio->writeRequest=NULL;
00421 }
00422 else {
00423
00424 DBG_INFO(GWEN_LOGDOMAIN, "Write request not registered with this io layer");
00425 return GWEN_ERROR_INVALID;
00426 }
00427 break;
00428
00429 default:
00430 break;
00431 }
00432
00433 return 0;
00434 }
00435
00436
00437
00438 int GWEN_Io_LayerFile_HasWaitingRequests(GWEN_IO_LAYER *io) {
00439 GWEN_IO_LAYER_FILE *xio;
00440
00441 assert(io);
00442 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_FILE, io);
00443 assert(xio);
00444
00445 if (xio->readRequest || xio->writeRequest)
00446 return 1;
00447 else
00448 return 0;
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463